home *** CD-ROM | disk | FTP | other *** search
/ Super PC 34 / Super PC 34 (Shareware).iso / spc / UTIL / DJGPP2 / V2 / DJLSR200.ZIP / src / libemu / emu387.cc next >
Encoding:
C/C++ Source or Header  |  1995-11-12  |  62.2 KB  |  3,528 lines

  1. /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <signal.h>
  5. #include <setjmp.h>
  6.  
  7. extern char __libemu_ident_string[];
  8. static char *id = __libemu_ident_string;
  9.  
  10. #define EXP_BIAS 16383
  11. #define EXP_MAX 32766
  12.  
  13. #define SIGN_POS    0
  14. #define SIGN_NEG    1
  15.  
  16. #define TW_V    0    // valid
  17. #define TW_Z    1    // zero
  18. #define TW_S    2    // special
  19. #define TW_E    3    // empty
  20.  
  21. #define EX_SO    0x02C1    // stack overflow
  22. #define EX_SU    0x00C1    // stack underflow
  23. #define EX_P    0x00A0    // loss of precision
  24. #define EX_U    0x0090    // underflow
  25. #define EX_O    0x0088    // overflow
  26. #define EX_Z    0x0084    // divide by zero
  27. #define EX_D    0x0082    // denormalized operand
  28. #define EX_I    0x0081    // invalid operation
  29.  
  30. #define SW_B    0x8000    // backward compatibility (=ES)
  31. #define SW_C3    0x4000    // condition bit 3
  32. #define SW_TOP    0x3800    // top of stack
  33. #define SW_TOPS 0x0800    // scale for TOS
  34. #define SW_C2    0x0400    // condition bit 2
  35. #define SW_C1    0x0200    // condition bit 1
  36. #define SW_C0    0x0100    // condition bit 0
  37. #define SW_ES    0x0080    // exception summary
  38. #define SW_SF    0x0040    // stack fault
  39. #define SW_PE    0x0020    // loss of precision
  40. #define SW_UE    0x0010    // underflow
  41. #define SW_OE    0x0008    // overflow
  42. #define SW_ZE    0x0004    // divide by zero
  43. #define SW_DE    0x0002    // denormalized operand
  44. #define SW_IE    0x0001    // invalid operation
  45.  
  46. #define CW_RC    0x0C00    // rounding control
  47. #define CW_PC    0x0300    // precision control
  48. #define CW_PM    0x0020    // precision mask
  49. #define CW_UM    0x0010    // underflow mask
  50. #define CW_OM    0x0008    // overflow mask
  51. #define CW_ZM    0x0004    // divide by zero mask
  52. #define CW_DM    0x0002    // denormalized operand mask
  53. #define CW_IM    0x0001    // invalid operation mask
  54. #define CW_EXM    0x007f    // all masks
  55.  
  56. #define RC_RND    0x0000
  57. #define RC_DOWN    0x0400
  58. #define RC_UP    0x0800
  59. #define RC_CHOP    0x0C00
  60.  
  61. #define COMP_A_GT_B    1
  62. #define COMP_A_EQ_B    2
  63. #define COMP_A_LT_B    3
  64. #define COMP_NOCOMP    4
  65. #define COMP_NAN    0x40
  66. #define COMP_SNAN    0x80
  67.  
  68. #define NAN_NONE 0
  69. #define NAN_SNAN 1
  70. #define NAN_QNAN 2
  71.  
  72. struct reg {
  73.   char sign;
  74.   char tag;
  75.   short exp;
  76.   unsigned sigl;
  77.   unsigned sigh;
  78. };
  79.  
  80. typedef void (*FUNC)();
  81.  
  82. static int modrm;
  83. static unsigned eax;
  84. static unsigned ebx;
  85. static unsigned ecx;
  86. static unsigned edx;
  87. static unsigned esi;
  88. static unsigned edi;
  89. static unsigned ebp;
  90. static unsigned esp;
  91. static unsigned char *eip;
  92.  
  93. static jmp_buf jumpbuf;
  94.  
  95. static int status_word = 0;
  96. static int control_word = 0x77e;
  97. static reg regs[8] = {
  98.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  99.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  100.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  101.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  102.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  103.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  104.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  105.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  106. };
  107. static int top = 0;
  108.  
  109. static reg CONST_1 = { SIGN_POS, TW_V, EXP_BIAS, 0x00000000, 0x80000000 };
  110. static reg CONST_L2T = { SIGN_POS, TW_V, EXP_BIAS+1, 0xcd1b8afe, 0xd49a784b };
  111. static reg CONST_L2E = { SIGN_POS, TW_V, EXP_BIAS, 0x5c17f0bc, 0xb8aa3b29 };
  112. static reg CONST_PI = { SIGN_POS, TW_V, EXP_BIAS+1, 0x2168c235, 0xc90fdaa2 };
  113. static reg CONST_PI2 = { SIGN_POS, TW_V, EXP_BIAS, 0x2168c235, 0xc90fdaa2 };
  114. static reg CONST_LG2 = { SIGN_POS, TW_V, EXP_BIAS-2, 0xfbcff799, 0x9a209a84 };
  115. static reg CONST_LN2 = { SIGN_POS, TW_V, EXP_BIAS-1, 0xd1cf79ac, 0xb17217f7 };
  116. static reg CONST_Z = { SIGN_POS, TW_Z, 0, 0x0, 0x0 };
  117.  
  118. static reg CONST_PINF = { SIGN_POS, TW_S, EXP_MAX+1, 0x00000000, 0x80000000 };
  119. static reg CONST_NINF = { SIGN_NEG, TW_S, EXP_MAX+1, 0x00000000, 0x80000000 };
  120. static reg CONST_NAN = { SIGN_NEG, TW_S, EXP_MAX+1, 0x00000000, 0xC0000000 };
  121.  
  122. inline reg& st(int which=0) { return regs[(top+which)&7]; }
  123.  
  124. extern "C" _write(int,void*,int);
  125.  
  126. static inline int val_same(reg& a, reg& b)
  127. {
  128.   if (a.sign != b.sign || a.exp != b.exp || a.sigl != b.sigl || a.sigh != b.sigh)
  129.     return 0;
  130.   return 1;
  131. }
  132.  
  133. static inline int is_zero(reg a)
  134. {
  135.   return (a.exp == 0 && a.sigl == 0 && a.sigh == 0);
  136. }
  137.  
  138. #ifndef eprintf
  139. static void eprintf(const char *f, ...)
  140. {
  141.   char buf[1000];
  142.   vsprintf(buf, f, (&f)+1);
  143.   _write(1, buf, strlen(buf));
  144. }
  145. #endif
  146.  
  147. /* extern "C" void djshld(void *); */
  148. #define djshld(q) ((*(long long unsigned *)(q)) <<= 1)
  149. #define djshrd(q) ((*(long long unsigned *)(q)) >>= 1)
  150.  
  151. static int nan_type(reg& r)
  152. {
  153.   if (r.exp != EXP_MAX+1)
  154.     return NAN_NONE;
  155.   if (r.sigh & 0x40000000)
  156.     return NAN_QNAN;
  157.   return NAN_SNAN;
  158. }
  159.  
  160. static int compare(reg& a, reg& b)
  161. {
  162.   int a_inf, b_inf; // 0=no, 1=pos, -1=neg
  163.   a_inf = 0;
  164.   if (val_same(a, CONST_PINF))
  165.     a_inf = 1;
  166.   else if (val_same(a, CONST_NINF))
  167.     a_inf = -1;
  168.   b_inf = 0;
  169.   if (val_same(b, CONST_PINF))
  170.     b_inf = 1;
  171.   else if (val_same(b, CONST_NINF))
  172.     b_inf = -1;
  173.   if (a_inf || b_inf)
  174.   {
  175.     if (a_inf == 1)
  176.       if (b_inf == 1)
  177.         return COMP_A_EQ_B;
  178.       else
  179.         return COMP_A_GT_B;
  180.     if (b_inf == 1)
  181.       return COMP_A_LT_B;
  182.  
  183.     if (a_inf == -1)
  184.       if (b_inf == -1)
  185.         return COMP_A_EQ_B;
  186.       else
  187.         return COMP_A_LT_B;
  188.     if (b_inf == -1)
  189.       return COMP_A_GT_B;
  190.   }
  191.   int a_nan = nan_type(a);
  192.   int b_nan = nan_type(b);
  193.   if (a_nan || b_nan)
  194.   {
  195.     if ((a_nan == NAN_SNAN) || (b_nan == NAN_SNAN))
  196.       return COMP_NOCOMP | COMP_SNAN | COMP_NAN;
  197.     return COMP_NOCOMP | COMP_NAN;
  198.   }
  199.   if (a.sign != b.sign)
  200.   {
  201.     if ((a.tag == TW_Z) && (b.tag == TW_Z))
  202.       return COMP_A_EQ_B;
  203.     if (a.sign == SIGN_POS)
  204.       return COMP_A_GT_B;
  205.     return COMP_A_LT_B;
  206.   }
  207.   while (!(a.sigh & 0x80000000))
  208.   {
  209.     if (!a.exp)
  210.       break;
  211.     djshld(&a.sigl);
  212.     a.exp--;
  213.   }
  214.   while (!(b.sigh & 0x80000000))
  215.   {
  216.     if (!b.exp)
  217.       break;
  218.     djshld(&b.sigl);
  219.     b.exp--;
  220.   }
  221.   int diff = a.exp - b.exp;
  222.   if (diff == 0) diff = a.sigh - b.sigh;
  223.   if (diff == 0) diff = a.sigl - b.sigl;
  224.   if (a.sign == SIGN_NEG)
  225.     diff = -diff;
  226.   if (diff > 0) return COMP_A_GT_B;
  227.   if (diff < 0) return COMP_A_LT_B;
  228.   return COMP_A_EQ_B;
  229. }
  230.  
  231. static void emu_printall()
  232. {
  233.   static const char *tag_desc[] = { "Valid", "Zero", "Special", "Empty" };
  234.   status_word = status_word & ~SW_TOP;
  235.   status_word += (top&7) * SW_TOPS;
  236.   eprintf("  SW: 0x%04x  top=%d cc=%d%d%d%d    ", status_word, top&7,
  237.     status_word & SW_C3?1:0, status_word & SW_C2?1:0,
  238.     status_word & SW_C1?1:0, status_word & SW_C0?1:0);
  239.   eprintf("CW: 0x%04x\r\n", control_word);
  240.   for (int i=0; i<8; i++)
  241.   {
  242.     reg *r = &st(i);
  243.     switch (r->tag)
  244.     {
  245.       case TW_E:
  246.         continue;
  247.         eprintf("st(%d)                                ", i);
  248.         break;
  249.       case TW_Z:
  250.         eprintf("st(%d) %c .0000 0000 0000 0000         ",
  251.                 i, r->sign ? '-' : '+');
  252.         break;
  253.       case TW_S:
  254.       case TW_V:
  255.         eprintf("st(%d) %c .%04x %04x %04x %04x e%+-6d ", i,
  256.           r->sign ? '-' : '+',
  257.           (long)(r->sigh >> 16),
  258.           (long)(r->sigh & 0xFFFF),
  259.           (long)(r->sigl >> 16),
  260.           (long)(r->sigl & 0xFFFF),
  261.           r->exp - EXP_BIAS + 1);
  262.     }
  263.     eprintf("%s\r\n", tag_desc[r->tag]);
  264.   }
  265. }
  266.  
  267. static struct {
  268.   int type;
  269.   const char *name;
  270. } ex_names[] = {
  271.   { EX_SO, "stack overflow" },
  272.   { EX_SU, "stack underflow" },
  273.   { EX_P, "loss of precision" },
  274.   { EX_U, "underflow" },
  275.   { EX_O, "overflow" },
  276.   { EX_Z, "divide by zero" },
  277.   { EX_D, "denormalized operand" },
  278.   { EX_I, "invalid operation" },
  279.   { 0,0 }
  280. };
  281.  
  282. static void exception(int n)
  283. {
  284.   int i;
  285.   status_word |= n;
  286.   if (n == EX_SU)
  287.     status_word &= ~SW_C1;
  288.   for (i=0; ex_names[i].type; i++)
  289.     if (ex_names[i].type == n)
  290.       break;
  291.   if (~control_word & n & CW_EXM)
  292.   {
  293.     if (ex_names[i].type)
  294.       eprintf("80387 Exception: %s!\r\n", ex_names[i].name);
  295.     else
  296.       eprintf("80387 Exception: 0x%04x!\r\n", n);
  297.     emu_printall();
  298.     
  299.     longjmp(jumpbuf,1);
  300.   }
  301. }
  302.  
  303. static void emu_bad()
  304. {
  305.   eprintf("Unimplemented 80387 Opcode at eip=0x%08x : %02x", eip-2, eip[-2]);
  306.   if (eip[-1] > 0277)
  307.     eprintf(" %02x", eip[-1]);
  308.   else
  309.     eprintf(" /%d", (eip[-1]>>3)&7);
  310.   eprintf(" - e%d%d", eip[-2]&7, (eip[-1]>>3)&7);
  311.   if (eip[-1] > 0277)
  312.     eprintf(" s%d", eip[-1]&7);
  313.   eprintf("\r\n");
  314.   exception(EX_I);
  315. }
  316.  
  317. static void setcc(int cc)
  318. {
  319.   status_word &= ~(SW_C0|SW_C1|SW_C2|SW_C3);
  320.   status_word |= cc & (SW_C0|SW_C1|SW_C2|SW_C3);
  321. }
  322.  
  323. static int full()
  324. {
  325.   if (st(7).tag != TW_E)
  326.   {
  327.     exception(EX_SO);
  328.     top--;
  329.     st(0) = CONST_NAN;
  330.     return 1;
  331.   }
  332.   return 0;
  333. }
  334.  
  335. static int empty(int i=0)
  336. {
  337.   if (st(i).tag == TW_E)
  338.   {
  339.     exception(EX_SU);
  340.     return 1;
  341.   }
  342.   return 0;
  343. }
  344.  
  345. static int sregval(int reg1, int mod)
  346. {
  347.   switch (reg1)
  348.   {
  349.     case 0: return eax;
  350.     case 1: return ecx;
  351.     case 2: return edx;
  352.     case 3: return ebx;
  353.     case 4: return (mod==-1) ? 0 : esp;
  354.     case 5: return mod ? ebp : 0; // data
  355.     case 6: return esi;
  356.     case 7: return edi;
  357.   }
  358.   return 0;
  359. }
  360.  
  361. static int scale[] = { 1, 2, 4, 8 };
  362.  
  363. static int getsib()
  364. {
  365.   int mod = modrm >> 6;
  366.   int sib = *eip++;
  367.   int ss = sib>>6;
  368.   int index = (sib>>3) & 7;
  369.   int base = sib & 7;
  370.   int rv = sregval(base, mod) + sregval(index, -1) * scale[ss];
  371.   int rv2;
  372.   switch (mod)
  373.   {
  374.     case 1:
  375.       rv2 = *(signed char *)eip++;
  376.       rv += rv2;
  377.       break;
  378.     case 0:
  379.       if (base != 5)
  380.         break;
  381.     case 2:
  382.       ((unsigned char *)&rv2)[0] = *eip++;
  383.       ((unsigned char *)&rv2)[1] = *eip++;
  384.       ((unsigned char *)&rv2)[2] = *eip++;
  385.       ((unsigned char *)&rv2)[3] = *eip++;
  386.       rv += rv2;
  387.       break;
  388.   }
  389.   return rv;
  390. }
  391.  
  392. static int regval(int reg1, int mod)
  393. {
  394.   switch (reg1)
  395.   {
  396.     case 0: return eax;
  397.     case 1: return ecx;
  398.     case 2: return edx;
  399.     case 3: return ebx;
  400.     case 4: return getsib();
  401.     case 5: return mod ? ebp : 0; // data
  402.     case 6: return esi;
  403.     case 7: return edi;
  404.   }
  405.   return 0;
  406. }
  407.  
  408. static void *get_modrm()
  409. {
  410.   int mod = modrm>>6;
  411.   int rm = modrm & 7;
  412.   int rv;
  413.   switch (mod)
  414.   {
  415.     case 0:
  416.       if (rm == 5)
  417.       {
  418.         ((unsigned char *)&rv)[0] = *eip++;
  419.         ((unsigned char *)&rv)[1] = *eip++;
  420.         ((unsigned char *)&rv)[2] = *eip++;
  421.         ((unsigned char *)&rv)[3] = *eip++;
  422.       }
  423.       else
  424.         rv = regval(rm, mod);
  425.       break;
  426.     case 1:
  427.       if (rm != 4)
  428.         rv = (*(signed char *)eip++) + regval(rm, mod);
  429.       else
  430.         rv = regval(rm, mod);
  431.       break;
  432.     case 2:
  433.       if (rm != 4)
  434.       {
  435.         ((unsigned char *)&rv)[0] = *eip++;
  436.         ((unsigned char *)&rv)[1] = *eip++;
  437.         ((unsigned char *)&rv)[2] = *eip++;
  438.         ((unsigned char *)&rv)[3] = *eip++;
  439.         rv += regval(rm, mod);
  440.       }
  441.       else
  442.         rv = regval(rm, mod);
  443.       break;
  444.     case 3:
  445.       eprintf("Attempt to get address from mod = 3\r\n");
  446.       longjmp(jumpbuf,1);
  447.   }
  448. //  eprintf("modrm returning 0x%x\r\n", rv);
  449.   return (void *)rv;
  450. }
  451.  
  452.  
  453.  
  454. static void r_uadd(reg& a, reg& b, reg& s) // signs ignored
  455. {
  456.   reg t;
  457.   int dif = a.exp - b.exp;
  458.   if (!dif) dif = a.sigh - b.sigh;
  459.   if (!dif) dif = a.sigl - b.sigl;
  460.   if (dif > 0)
  461.   {
  462.     s = a;
  463.     t = b;
  464.   }
  465.   else
  466.   {
  467.     s = b;
  468.     t = a;
  469.   }
  470.   if (s.exp - t.exp > 64)
  471.     return;
  472.   while (t.exp < s.exp)
  473.   {
  474.     t.exp ++;
  475.     djshrd(&t.sigl);
  476.   }
  477.   unsigned short *ss, *ts;
  478.   unsigned long tmp;
  479.   ss = (unsigned short *)&s.sigl;
  480.   ts = (unsigned short *)&t.sigl;
  481.   tmp = 0;
  482.   for (int i=4; i>0; i--)
  483.   {
  484.     tmp += (unsigned long)*ss + (unsigned long)*ts;
  485.     *ss = tmp;
  486.     ss++;
  487.     ts++;
  488.     tmp >>= 16;
  489.   }
  490.   if (tmp)
  491.   {
  492.     djshrd(&s.sigl);
  493.     s.exp++;
  494.     s.sigh |= 0x80000000;
  495.   }
  496.   if (!(s.sigh | s.sigl))
  497.   {
  498.     s.exp = 0;
  499.     s.tag = TW_Z;
  500.   }
  501.   else
  502.   {
  503.     while (!(s.sigh & 0x80000000))
  504.     {
  505.       if (s.exp == 0)
  506.         return;
  507.       djshld(&s.sigl);
  508.       s.exp--;
  509.     }
  510.   }
  511. }
  512.  
  513. static void r_usub(reg& a, reg& b, reg& d) // a > b
  514. {
  515.   reg t;
  516.   d = a;
  517.   t = b;
  518.  
  519.   if (d.exp - t.exp > 64)
  520.     return;
  521.   while (t.exp < d.exp)
  522.   {
  523.     t.exp ++;
  524.     djshrd(&t.sigl);
  525.   }
  526.   unsigned short *ss, *ts;
  527.   long tmp;
  528.   ss = (unsigned short *)&d.sigl;
  529.   ts = (unsigned short *)&t.sigl;
  530.   tmp = 0;
  531.   for (int i=4; i>0; i--)
  532.   {
  533.     tmp += (long)*ss - (long)*ts;
  534.     *ss = tmp;
  535.     ss++;
  536.     ts++;
  537.     tmp >>= 16;
  538.   }
  539.   if (!(d.sigh | d.sigl))
  540.   {
  541.     d.exp = 0;
  542.     d.tag = TW_Z;
  543.   }
  544.   else
  545.   {
  546.     while (!(d.sigh & 0x80000000))
  547.     {
  548.       if (d.exp == 0)
  549.         return;
  550.       djshld(&d.sigl);
  551.       d.exp--;
  552.     }
  553.   }
  554. }
  555.  
  556. static void r_sub(reg& a, reg& b, reg& d)
  557. {
  558.   if (b.tag == TW_Z)
  559.   {
  560.     d = a;
  561.     return;
  562.   }
  563.   if (a.tag == TW_Z)
  564.   {
  565.     d = b;
  566.     d.sign ^= SIGN_POS^SIGN_NEG;
  567.     return;
  568.   }
  569.   if (a.tag == TW_S)
  570.   {
  571.     d = a;
  572.     return;
  573.   }
  574.   if (b.tag == TW_S)
  575.   {
  576.     d = b;
  577.     d.sign ^= SIGN_POS^SIGN_NEG;
  578.     return;
  579.   }
  580.  
  581.   int mdif;
  582.   mdif = a.exp - b.exp;
  583.   if (!mdif)
  584.     mdif = a.sigh - b.sigh;
  585.   if (!mdif)
  586.     mdif = a.sigl - b.sigl;
  587.  
  588.   switch (a.sign*2 + b.sign)
  589.   {
  590.     case 0: // P - P
  591.     case 3: // N - N
  592.       if (mdif > 0)
  593.       {
  594.         r_usub(a, b, d);
  595.         d.sign = a.sign;
  596.       }
  597.       else
  598.       {
  599.         r_usub(b, a, d);
  600.         d.sign = a.sign ^ SIGN_POS^SIGN_NEG;
  601.       }
  602.       break;
  603.     case 1: // P - N
  604.       r_uadd(a, b, d);
  605.       d.sign = SIGN_POS;
  606.       break;
  607.     case 2: // N - P
  608.       r_uadd(a, b, d);
  609.       d.sign = SIGN_NEG;
  610.       break;
  611.   }
  612. }
  613.  
  614. static void r_add(reg& a, reg& b, reg& s)
  615. {
  616.   char old_sign;
  617.   if (a.tag == TW_Z)
  618.   {
  619.     s = b;
  620.     return;
  621.   }
  622.   if (b.tag == TW_Z)
  623.   {
  624.     s = a;
  625.     return;
  626.   }
  627.   if (a.tag == TW_S)
  628.   {
  629.     s = a;
  630.     return;
  631.   }
  632.   if (b.tag == TW_S)
  633.   {
  634.     s = b;
  635.     return;
  636.   }
  637.  
  638.   switch (a.sign*2 + b.sign)
  639.   {
  640.     case 0: // P + P
  641.     case 3: // N + N
  642.       r_uadd(a, b, s);
  643.       s.sign = a.sign;
  644.       break;
  645.     case 1: // P + N
  646.       old_sign = b.sign;
  647.       b.sign ^= SIGN_POS^SIGN_NEG;
  648.       r_sub(a, b, s);
  649.       b.sign = old_sign;
  650.       break;
  651.     case 2: // N + P
  652.       old_sign = a.sign;
  653.       a.sign ^= SIGN_POS^SIGN_NEG;
  654.       r_sub(b, a, s);
  655.       a.sign = old_sign;
  656.       break;
  657.   }
  658. }
  659.  
  660. static void normalize(reg& r)
  661. {
  662.   if (!(r.sigl | r.sigh))
  663.   {
  664.     r.exp = 0;
  665.     r.tag = TW_Z;
  666.     return;
  667.   }
  668.   if (r.exp > EXP_MAX)
  669.   {
  670.     r.tag = TW_S;
  671.     return;
  672.   }
  673.   while (!(r.sigh & 0x80000000))
  674.   {
  675.     if (r.exp == 0)
  676.       return;
  677.     djshld(&r.sigl);
  678.     r.exp--;
  679.   }
  680. }
  681.  
  682. static void r_mul(reg& a, reg& b, reg& s)
  683. {
  684.   if (a.tag == TW_Z)
  685.   {
  686.     s = CONST_Z;
  687.   }
  688.   else if (b.tag == TW_Z)
  689.   {
  690.     s = CONST_Z;
  691.   }
  692.   else if (a.tag == TW_S)
  693.   {
  694.     s = a;
  695.   }
  696.   else if (b.tag == TW_S)
  697.   {
  698.     s = b;
  699.   }
  700.   else
  701.   {
  702.     unsigned short sl[9], carry[10];
  703.     unsigned short *as = (unsigned short *)(&a.sigl);
  704.     unsigned short *bs = (unsigned short *)(&b.sigl);
  705.     unsigned long l, sum;
  706.     int ai, bi;
  707.     for (ai=0; ai<8; ai++)
  708.       sl[ai] = carry[ai] = 0;
  709.     for (ai = 0; ai < 4; ai++)
  710.       for (bi = 0; bi < 4; bi++)
  711.       {
  712.         l = as[ai] * bs[bi];
  713.  
  714.         sum = sl[ai+bi] + (l & 0xffff);
  715.         sl[ai+bi] = sum & 0xffff;
  716.  
  717.         sum = sl[ai+bi+1] + (l>>16) + (sum>>16);
  718.         sl[ai+bi+1] = sum & 0xffff;
  719.  
  720.         carry[ai+bi+2] += sum>>16;
  721.       }
  722.     for (ai=0; ai<8; ai++)
  723.     {
  724.       if (carry[ai])
  725.       {
  726.         sum = sl[ai] + carry[ai];
  727.         sl[ai] = sum & 0xffff;
  728.         carry[ai+1] += sum>>16;
  729.       }
  730.     }
  731.     s.sigl = *(long *)(sl+4);
  732.     s.sigh = *(long *)(sl+6);
  733.     s.exp = a.exp + b.exp - EXP_BIAS + 1;
  734.     s.tag = TW_V;
  735.   }
  736.   if (a.sign == b.sign)
  737.     s.sign = SIGN_POS;
  738.   else
  739.     s.sign = SIGN_NEG;
  740.   normalize(s);
  741. }
  742.  
  743. static void r_div(reg& a, reg& b, reg& q)
  744. {
  745.   if (a.tag == TW_S)
  746.   {
  747.     if (val_same(a, CONST_PINF))
  748.       q = a;
  749.     else if (val_same(a, CONST_NINF))
  750.       q = a;
  751.   }
  752.   else if (b.tag == TW_S)
  753.   {
  754.     if (val_same(b, CONST_PINF))
  755.       q = CONST_Z;
  756.     else if (val_same(b, CONST_NINF))
  757.       q = CONST_Z;
  758.   }
  759.   else if (a.tag == TW_Z)
  760.   {
  761.     q = a;
  762.   }
  763.   else if (b.tag == TW_Z)
  764.   {
  765.     exception(EX_Z);
  766.   }
  767.   else
  768.   {
  769.     q.exp = a.exp - b.exp + EXP_BIAS;
  770.     if (q.exp > EXP_MAX)
  771.       q = CONST_PINF;
  772.     else if (q.exp <= 0)
  773.       q = CONST_Z;
  774.     else
  775.     {
  776.       unsigned long long al, bl, ql, f;
  777.       int i;
  778.       al = *(unsigned long long *)(&a.sigl);
  779.       bl = *(unsigned long long *)(&b.sigl);
  780.       ql = 0;
  781.       f = (unsigned long long)1 << 63;
  782.       for (i=0; i<64; i++)
  783.       {
  784.         if (al >= bl)
  785.         {
  786.           al -= bl;
  787.           ql += f;
  788.         }
  789.         bl >>= 1;
  790.         f >>= 1;
  791.       }
  792.       *(unsigned long long *)(&q.sigl) = ql;
  793.       q.tag = TW_V;
  794.     }
  795.   }
  796.   if (a.sign == b.sign)
  797.     q.sign = SIGN_POS;
  798.   else
  799.     q.sign = SIGN_NEG;
  800.   normalize(q);
  801. }
  802.  
  803. static void r_mov(long double *s, reg& d)
  804. {
  805.   unsigned long *sp = (unsigned long *)s;
  806.   if (sp[2] & 0x8000)
  807.     d.sign = SIGN_NEG;
  808.   else
  809.     d.sign = SIGN_POS;
  810.   d.exp = sp[2] & 0x7fff;
  811.   d.sigh = sp[1];
  812.   d.sigl = sp[0];
  813.   d.tag = TW_V;
  814.   normalize(d);
  815. }
  816.  
  817. static void r_mov(double *s, reg& d)
  818. {
  819.   unsigned m64 = ((unsigned *)s)[1];
  820.   unsigned l64 = ((unsigned *)s)[0];
  821.   if (m64 & 0x80000000)
  822.     d.sign = SIGN_NEG;
  823.   else
  824.     d.sign = SIGN_POS;
  825.   if (!((m64 & 0x7fffffff) | (l64)))
  826.   {
  827.     int c = d.sign;
  828.     d = CONST_Z;
  829.     d.sign = c;
  830.     return;
  831.   }
  832.   d.exp = (int)((m64>>20)&0x7ff) - 1023 + EXP_BIAS;
  833.   d.sigh = ((m64 & 0xfffff)<<11) | 0x80000000;
  834.   d.sigh |= l64 >> 21;
  835.   d.sigl = l64 << 11;
  836.   d.tag = TW_V;
  837.   if ((m64 & 0x7ff00000) == 0x7ff00000)
  838.     d.exp = EXP_MAX+1;
  839.   normalize(d);
  840. }
  841.  
  842. static void r_mov(float *s, reg& d)
  843. {
  844.   unsigned m32 = *(unsigned *)s;
  845.   if (m32 & 0x80000000)
  846.     d.sign = SIGN_NEG;
  847.   else
  848.     d.sign = SIGN_POS;
  849.   if (!(m32 & 0x7fffffff))
  850.   {
  851.     int c = d.sign;
  852.     d = CONST_Z;
  853.     d.sign = c;
  854.     return;
  855.   }
  856.   d.exp = (int)((m32>>23)&0xff) - 127 + EXP_BIAS;
  857.   d.sigh = ((m32 & 0x7fffff)<<8) | 0x80000000;
  858.   d.sigl = 0;
  859.   d.tag = TW_V;
  860.   if ((m32 & 0x7f800000) == 0x7f800000)
  861.     d.exp = EXP_MAX+1;
  862.   normalize(d);
  863. }
  864.  
  865. static void r_mov(long long *_s, reg& d)
  866. {
  867.   long long s = *_s;
  868.   if (s == 0)
  869.   {
  870.     d = CONST_Z;
  871.     return;
  872.   }
  873.  
  874.   if (s > 0)
  875.     d.sign = SIGN_POS;
  876.   else
  877.   {
  878.     s = -s;
  879.     d.sign = SIGN_NEG;
  880.   }
  881.  
  882.   int e = EXP_BIAS + 63;
  883.   while (s >= 0)
  884.   {
  885.     djshld(&s);
  886.     e -= 1;
  887.   }
  888.   d.sigh = s >> 32;
  889.   d.sigl = s;
  890.   d.exp = e;
  891.   d.tag = TW_V;
  892.   normalize(d);
  893. }
  894.  
  895. static void r_mov(long *_s, reg& d)
  896. {
  897.   long s = *_s;
  898.   if (s == 0)
  899.   {
  900.     d = CONST_Z;
  901.     return;
  902.   }
  903.  
  904.   if (s > 0)
  905.     d.sign = SIGN_POS;
  906.   else
  907.   {
  908.     s = -s;
  909.     d.sign = SIGN_NEG;
  910.   }
  911.  
  912.   int e = EXP_BIAS + 31;
  913.   while (!(s & 0x80000000))
  914.   {
  915.     s <<= 1;
  916.     e -= 1;
  917.   }
  918.   d.sigh = s;
  919.   d.sigl = 0;
  920.   d.exp = e;
  921.   d.tag = TW_V;
  922.   normalize(d);
  923. }
  924.  
  925. static void r_mov(short *_s, reg& d)
  926. {
  927.   int s = *_s;
  928.   if (s == 0)
  929.   {
  930.     d = CONST_Z;
  931.     return;
  932.   }
  933.  
  934.   if (s > 0)
  935.     d.sign = SIGN_POS;
  936.   else
  937.   {
  938.     s = -s;
  939.     d.sign = SIGN_NEG;
  940.   }
  941.  
  942.   int e = EXP_BIAS + 15;
  943.   while (!(s & 0x8000))
  944.   {
  945.     s <<= 1;
  946.     e -= 1;
  947.   }
  948.   d.sigh = s << 16;
  949.   d.sigl = 0;
  950.   d.exp = e;
  951.   d.tag = TW_V;
  952.   normalize(d);
  953. }
  954.  
  955. static void r_mov(char *s, reg& d)
  956. {
  957.   int side=1, pos=8;
  958.   long long l;
  959.   l = 0;
  960.   for (int i=0; i<18; i++)
  961.   {
  962.     l *= 10;
  963.     switch (side)
  964.     {
  965.       case 0:
  966.         l += s[pos] & 0x0f;
  967.         side = 1;
  968.         pos--;
  969.         break;
  970.       case 1:
  971.         l += s[pos] >> 4;
  972.         side = 0;
  973.         break;
  974.     }
  975.   }
  976.   r_mov(&l, d);
  977.   if (s[9] & 0x80)
  978.     d.sign = SIGN_NEG;
  979. }
  980.  
  981. //=============================================================================
  982.  
  983. static void round_to_int(reg& r) // r gets mangled such that sig is int, sign
  984. {
  985.   int more_than_half = 0;
  986.   int half_or_more = 0;
  987.   if (r.tag == TW_Z)
  988.   {
  989.     return;
  990.   }
  991.   while (r.exp < EXP_BIAS+62)
  992.   {
  993.     if (r.sigl & 1)
  994.       more_than_half = 1;
  995.     djshrd(&r.sigl);
  996.     r.exp++;
  997.   }
  998.   while (r.exp < EXP_BIAS+63)
  999.   {
  1000.     if (r.sigl & 1)
  1001.       half_or_more = 1;
  1002.     djshrd(&r.sigl);
  1003.     r.exp++;
  1004.   }
  1005.   if (r.exp > EXP_BIAS+63)
  1006.   {
  1007.     r.sigl = r.sigh = ~0;
  1008.     return;
  1009.   }
  1010.   switch (control_word & CW_RC)
  1011.   {
  1012.     case RC_RND:
  1013.       if (half_or_more)
  1014.         if (more_than_half) // nearest
  1015.           (*(long long *)(&r.sigl)) ++;
  1016.         else
  1017.           if (r.sigl & 1) // odd?
  1018.             (*(long long *)(&r.sigl)) ++;
  1019.       break;
  1020.     case RC_DOWN:
  1021.       if ((half_or_more||more_than_half) && r.sign)
  1022.         (*(long long *)(&r.sigl)) ++;
  1023.       break;
  1024.     case RC_UP:
  1025.       if ((half_or_more||more_than_half) && !r.sign)
  1026.         (*(long long *)(&r.sigl)) ++;
  1027.       break;
  1028.     case RC_CHOP:
  1029.       break;
  1030.   }
  1031. }
  1032.  
  1033. static void r_mov(reg& s, long double *d)
  1034. {
  1035.   ((short *)d)[4] = s.exp + s.sign*0x8000;
  1036.   ((long *)d)[0] = s.sigl;
  1037.   ((long *)d)[1] = s.sigh;
  1038. }
  1039.  
  1040. static void r_mov(reg& s, double *d)
  1041. {
  1042.   unsigned long *l = (unsigned long *)d;
  1043.   if (s.tag == TW_Z)
  1044.   {
  1045.     l[0] = 0;
  1046.     l[1] = 0;
  1047.   }
  1048.   else
  1049.   {
  1050.     l[0] = (s.sigl >> 11) | (s.sigh << 21);
  1051.     l[1] = ((s.sigh >> 11) & 0xfffff) | (((s.exp-EXP_BIAS+1023) & 0x7ff) << 20);
  1052.   }
  1053.   if (s.sign)
  1054.     l[1] |= 0x80000000;
  1055. }
  1056.  
  1057. static void r_mov(reg& s, float *d)
  1058. {
  1059.   long f;
  1060.   if (s.tag == TW_Z)
  1061.   {
  1062.     f = 0;
  1063.   }
  1064.   else
  1065.   {
  1066.     f = (s.sigh >> 8) & 0x007fffff;
  1067.     f |= ((s.exp-EXP_BIAS+127) & 0xff) << 23;
  1068.   }
  1069.   if (s.sign)
  1070.     f |= 0x80000000;
  1071.   *(long *)d = f;
  1072. }
  1073.  
  1074. static void r_mov(reg& s, long long *d)
  1075. {
  1076.   reg t;
  1077.   t = s;
  1078.   round_to_int(t);
  1079.   ((long *)d)[0] = t.sigl;
  1080.   ((long *)d)[1] = t.sigh;
  1081.   if (t.sign)
  1082.     *d = - *d;
  1083. }
  1084.  
  1085. static void r_mov(reg& s, long *d)
  1086. {
  1087.   reg t;
  1088.   t = s;
  1089.   round_to_int(t);
  1090.   if (t.sigh || (t.sigl & 0x80000000))
  1091.     *d = -1;
  1092.   else
  1093.     *d = s.sign ? -t.sigl : t.sigl;
  1094. }
  1095.  
  1096. static void r_mov(reg& s, short *d)
  1097. {
  1098.   reg t;
  1099.   t = s;
  1100.   round_to_int(t);
  1101.   if (t.sigh || (t.sigl & 0xFFFF8000))
  1102.     *d = -1;
  1103.   else
  1104.     *d = s.sign ? -t.sigl : t.sigl;
  1105. }
  1106.  
  1107. static void r_mov(reg& s, char *d)
  1108. {
  1109.   reg t;
  1110.   t = s;
  1111.   round_to_int(t);
  1112.   long long ll = *(long long *)(&t.sigl);
  1113.   int side = 0;
  1114.   int r, i;
  1115.   for (i=0; i<10; i++)
  1116.     d[i] = 0;
  1117.   int pos=0;
  1118.   for (i=0; i<18; i++)
  1119.   {
  1120.     r = ll % 10;
  1121.     ll /= 10;
  1122.     if (side)
  1123.     {
  1124.       d[pos] |= r << 4;
  1125.       side = 0;
  1126.       pos++;
  1127.     }
  1128.     else
  1129.     {
  1130.       d[pos] |= r;
  1131.       side = 1;
  1132.     }
  1133.   }
  1134.   if (s.sign == SIGN_NEG)
  1135.     d[9] = 0x80;
  1136. }
  1137.  
  1138. static void emu_00()
  1139. {
  1140.   if (empty())
  1141.     return;
  1142.   if (modrm > 0277)
  1143.   {
  1144.     // fadd st,st(i)
  1145.     int i = modrm & 7;
  1146.     if (empty(i))
  1147.       return;
  1148.     reg tmp;
  1149.     r_add(st(), st(i), tmp);
  1150.     st() = tmp;
  1151.     return;
  1152.   }
  1153.   else
  1154.   {
  1155.     // fadd m32real
  1156.     reg t1, t2;
  1157.     r_mov((float *)get_modrm(), t1);
  1158.     r_add(t1, st(), t2);
  1159.     st() = t2;
  1160.   }
  1161. }
  1162.  
  1163. static void emu_01()
  1164. {
  1165.   if (empty())
  1166.     return;
  1167.   if (modrm > 0277)
  1168.   {
  1169.     // fmul st,st(i)
  1170.     int i = modrm & 7;
  1171.     if (empty(i))
  1172.       return;
  1173.     reg t;
  1174.     r_mul(st(), st(i), t);
  1175.     st() = t;
  1176.   }
  1177.   else
  1178.   {
  1179.     // fmul m32real
  1180.     reg t, t2;
  1181.     r_mov((float *)get_modrm(), t);
  1182.     r_mul(st(), t, t2);
  1183.     st() = t2;
  1184.   }
  1185. }
  1186.  
  1187. static void emu_02()
  1188. {
  1189.   if (empty())
  1190.     return;
  1191.   if (modrm > 0277)
  1192.   {
  1193.     // fcom st(i)
  1194.     if (empty(modrm&7))
  1195.     {
  1196.       setcc(SW_C3|SW_C2|SW_C0);
  1197.       return;
  1198.     }
  1199.     int c = compare(st(), st(modrm&7));
  1200.     int f;
  1201.     if (c & COMP_NAN)
  1202.     {
  1203.       exception(EX_I);
  1204.       f = SW_C3 | SW_C2 | SW_C0;
  1205.     }
  1206.     else
  1207.       switch (c)
  1208.       {
  1209.         case COMP_A_LT_B:
  1210.           f = SW_C0;
  1211.           break;
  1212.         case COMP_A_EQ_B:
  1213.           f = SW_C3;
  1214.           break;
  1215.         case COMP_A_GT_B:
  1216.           f = 0;
  1217.           break;
  1218.         case COMP_NOCOMP:
  1219.           f = SW_C3 | SW_C2 | SW_C0;
  1220.           break;
  1221.       }
  1222.     setcc(f);
  1223.     
  1224.   }
  1225.   else
  1226.   {
  1227.     // fcom m32real
  1228.     reg t;
  1229.     r_mov((float *)get_modrm(), t);
  1230.     int c = compare(st(), t);
  1231.     int f;
  1232.     if (c & COMP_NAN)
  1233.     {
  1234.       exception(EX_I);
  1235.       f = SW_C3 | SW_C2 | SW_C0;
  1236.     }
  1237.     else
  1238.       switch (c)
  1239.       {
  1240.         case COMP_A_LT_B:
  1241.           f = SW_C0;
  1242.           break;
  1243.         case COMP_A_EQ_B:
  1244.           f = SW_C3;
  1245.           break;
  1246.         case COMP_A_GT_B:
  1247.           f = 0;
  1248.           break;
  1249.         case COMP_NOCOMP:
  1250.           f = SW_C3 | SW_C2 | SW_C0;
  1251.           break;
  1252.       }
  1253.     setcc(f);
  1254.   }
  1255. }
  1256.  
  1257. static void emu_03()
  1258. {
  1259.   if (empty())
  1260.     return;
  1261.   if (modrm > 0277)
  1262.   {
  1263.     // fcomp st(i)
  1264.     if (empty(modrm&7))
  1265.     {
  1266.       setcc(SW_C3|SW_C2|SW_C0);
  1267.       return;
  1268.     }
  1269.     int c = compare(st(), st(modrm&7));
  1270.     st().tag = TW_E;
  1271.     top++;
  1272.     int f;
  1273.     if (c & COMP_NAN)
  1274.     {
  1275.       exception(EX_I);
  1276.       f = SW_C3 | SW_C2 | SW_C0;
  1277.     }
  1278.     else
  1279.       switch (c)
  1280.       {
  1281.         case COMP_A_LT_B:
  1282.           f = SW_C0;
  1283.           break;
  1284.         case COMP_A_EQ_B:
  1285.           f = SW_C3;
  1286.           break;
  1287.         case COMP_A_GT_B:
  1288.           f = 0;
  1289.           break;
  1290.         case COMP_NOCOMP:
  1291.           f = SW_C3 | SW_C2 | SW_C0;
  1292.           break;
  1293.       }
  1294.     setcc(f);
  1295.     
  1296.   }
  1297.   else
  1298.   {
  1299.     // fcom m32real
  1300.     reg t;
  1301.     r_mov((float *)get_modrm(), t);
  1302.     int c = compare(st(), t);
  1303.     st().tag = TW_E;
  1304.     top++;
  1305.     int f;
  1306.     if (c & COMP_NAN)
  1307.     {
  1308.       exception(EX_I);
  1309.       f = SW_C3 | SW_C2 | SW_C0;
  1310.     }
  1311.     else
  1312.       switch (c)
  1313.       {
  1314.         case COMP_A_LT_B:
  1315.           f = SW_C0;
  1316.           break;
  1317.         case COMP_A_EQ_B:
  1318.           f = SW_C3;
  1319.           break;
  1320.         case COMP_A_GT_B:
  1321.           f = 0;
  1322.           break;
  1323.         case COMP_NOCOMP:
  1324.           f = SW_C3 | SW_C2 | SW_C0;
  1325.           break;
  1326.       }
  1327.     setcc(f);
  1328.   }
  1329. }
  1330.  
  1331. static void emu_04()
  1332. {
  1333.   if (empty())
  1334.     return;
  1335.   if (modrm > 0277)
  1336.   {
  1337.     // fsub st,st(i)
  1338.     int i = modrm & 7;
  1339.     if (empty(i))
  1340.       return;
  1341.     reg tmp;
  1342.     r_sub(st(), st(i), tmp);
  1343.     st() = tmp;
  1344.     return;
  1345.   }
  1346.   else
  1347.   {
  1348.     // fsub m32real
  1349.     reg t1, t2;
  1350.     r_mov((float *)get_modrm(), t1);
  1351.     r_sub(st(), t1, t2);
  1352.     st() = t2;
  1353.   }
  1354. }
  1355.  
  1356. static void emu_05()
  1357. {
  1358.   if (empty())
  1359.     return;
  1360.   if (modrm > 0277)
  1361.   {
  1362.     // fsubr st,st(i)
  1363.     int i = modrm & 7;
  1364.     if (empty(i))
  1365.       return;
  1366.     reg tmp;
  1367.     r_sub(st(i), st(), tmp);
  1368.     st() = tmp;
  1369.     return;
  1370.   }
  1371.   else
  1372.   {
  1373.     // fsubr m32real
  1374.     reg t1, t2;
  1375.     r_mov((float *)get_modrm(), t1);
  1376.     r_sub(t1, st(), t2);
  1377.     st() = t2;
  1378.   }
  1379. }
  1380.  
  1381. static void emu_06()
  1382. {
  1383.   if (empty())
  1384.     return;
  1385.   if (modrm > 0277)
  1386.   {
  1387.     // fdiv st,st(i)
  1388.     int i = modrm & 7;
  1389.     if (empty(i))
  1390.       return;
  1391.     reg t;
  1392.     r_div(st(), st(i), t);
  1393.     st() = t;
  1394.   }
  1395.   else
  1396.   {
  1397.     // fdiv m32real
  1398.     reg t, t2;
  1399.     r_mov((float *)get_modrm(), t);
  1400.     r_div(st(), t, t2);
  1401.     st() = t2;
  1402.   }
  1403. }
  1404.  
  1405. static void emu_07()
  1406. {
  1407.   if (empty())
  1408.     return;
  1409.   if (modrm > 0277)
  1410.   {
  1411.     // fdivr st,st(i)
  1412.     int i = modrm & 7;
  1413.     if (empty(i))
  1414.       return;
  1415.     reg t;
  1416.     r_div(st(i), st(), t);
  1417.     st() = t;
  1418.   }
  1419.   else
  1420.   {
  1421.     // fdivr m32real
  1422.     reg t, t2;
  1423.     r_mov((float *)get_modrm(), t);
  1424.     r_div(t, st(), t2);
  1425.     st() = t2;
  1426.   }
  1427. }
  1428.  
  1429. static void emu_10()
  1430. {
  1431.   if (full())
  1432.     return;
  1433.   if (modrm > 0277)
  1434.   {
  1435.     // fld st(i)
  1436.     int i = modrm & 7;
  1437.     if (empty(i))
  1438.       return;
  1439.     st(7) = st(i);
  1440.     top--;
  1441.     return;
  1442.   }
  1443.   else
  1444.   {
  1445.     // fld m32real
  1446.     top--;
  1447.     r_mov((float *)get_modrm(), st());
  1448.   }
  1449. }
  1450.  
  1451. static void emu_11()
  1452. {
  1453.   if (empty())
  1454.     return;
  1455.   if (modrm > 0277)
  1456.   {
  1457.     // fxch st(i)
  1458.     int i = modrm & 7;
  1459.     if (empty(i))
  1460.       return;
  1461.     reg t;
  1462.     t = st();
  1463.     st() = st(i);
  1464.     st(i) = t;
  1465.   }
  1466.   else
  1467.   {
  1468.     emu_bad();
  1469.   }
  1470. }
  1471.  
  1472. static void fnop()
  1473. {
  1474. }
  1475.  
  1476. static FUNC emu_12_table[] = {
  1477.   fnop, emu_bad, emu_bad, emu_bad, emu_bad, emu_bad, emu_bad, emu_bad
  1478. };
  1479.  
  1480. static void emu_12()
  1481. {
  1482.   if (modrm > 0277)
  1483.   {
  1484.     (emu_12_table[modrm&7])();
  1485.   }
  1486.   else
  1487.   {
  1488.     // fst m32real
  1489.     if (empty())
  1490.       return;
  1491.     r_mov(st(), (float *)get_modrm());
  1492.   }
  1493. }
  1494.  
  1495. static void emu_13()
  1496. {
  1497.   if (modrm > 0277)
  1498.   {
  1499.     emu_bad();
  1500.   }
  1501.   else
  1502.   {
  1503.     // fstp m32real
  1504.     if (empty())
  1505.       return;
  1506.     r_mov(st(), (float *)get_modrm());
  1507.     st().tag = TW_E;
  1508.     top++;
  1509.   }
  1510. }
  1511.  
  1512. static void fchs()
  1513. {
  1514.   if (empty())
  1515.     return;
  1516.   st().sign ^= SIGN_POS^SIGN_NEG;
  1517.   status_word &= ~SW_C1;
  1518. }
  1519.  
  1520. static void fabs()
  1521. {
  1522.   if (empty())
  1523.     return;
  1524.   st().sign = SIGN_POS;
  1525.   status_word &= ~SW_C1;
  1526. }
  1527.  
  1528. static void ftst()
  1529. {
  1530.   switch (st().tag)
  1531.   {
  1532.     case TW_Z:
  1533.       setcc(SW_C3);
  1534.       break;
  1535.     case TW_V:
  1536.       if (st().sign == SIGN_POS)
  1537.         setcc(0);
  1538.       else
  1539.         setcc(SW_C0);
  1540.       break;
  1541.     case TW_S:
  1542.       if (val_same(st(), CONST_PINF))
  1543.       {
  1544.         setcc(0);
  1545.         break;
  1546.       }
  1547.       else if (val_same(st(), CONST_NINF))
  1548.       {
  1549.         setcc(SW_C3);
  1550.         break;
  1551.       }
  1552.       setcc(SW_C0|SW_C2|SW_C3);
  1553.       exception(EX_I);
  1554.       break;
  1555.     case TW_E:
  1556.       setcc(SW_C0|SW_C2|SW_C3);
  1557.       exception(EX_SU);
  1558.       break;
  1559.   }
  1560. }
  1561.  
  1562. static void fxam()
  1563. {
  1564.   int c=0;
  1565.   switch (st().tag)
  1566.   {
  1567.     case TW_E:
  1568.       c = SW_C3|SW_C0;
  1569.       break;
  1570.     case TW_Z:
  1571.       c = SW_C3;
  1572.       break;
  1573.     case TW_V:
  1574.       if (st().sigh & 0x80000000)
  1575.         c = SW_C2;
  1576.       else
  1577.         c = SW_C3|SW_C2;
  1578.       break;
  1579.     case TW_S:
  1580.       if (val_same(st(), CONST_NAN))
  1581.         c = SW_C0;
  1582.       else if (val_same(st(), CONST_PINF))
  1583.         c = SW_C2|SW_C0;
  1584.       else if (val_same(st(), CONST_NINF))
  1585.         c = SW_C2|SW_C0;
  1586.       break;
  1587.   }
  1588.   if (st().sign == SIGN_NEG)
  1589.     c |= SW_C1;
  1590.   setcc(c);
  1591. }
  1592.  
  1593. static FUNC emu_14_table[] = {
  1594.   fchs, fabs, emu_bad, emu_bad, ftst, fxam, emu_bad, emu_bad
  1595. };
  1596.  
  1597. static void emu_14()
  1598. {
  1599.   if (modrm > 0277)
  1600.   {
  1601.     (emu_14_table[modrm&7])();
  1602.   }
  1603.   else
  1604.   {
  1605.     //
  1606.     emu_bad();
  1607.   }
  1608. }
  1609.  
  1610. static void fld_const(reg &c)
  1611. {
  1612.   if (full())
  1613.     return;
  1614.   top--;
  1615.   st() = c;
  1616.   status_word &= ~SW_C1;
  1617. }
  1618.  
  1619. static void fld1()
  1620. {
  1621.   fld_const(CONST_1);
  1622. }
  1623.  
  1624. static void fldl2t()
  1625. {
  1626.   fld_const(CONST_L2T);
  1627. }
  1628.  
  1629. static void fldl2e()
  1630. {
  1631.   fld_const(CONST_L2E);
  1632. }
  1633.  
  1634. static void fldpi()
  1635. {
  1636.   fld_const(CONST_PI);
  1637. }
  1638.  
  1639. static void fldlg2()
  1640. {
  1641.   fld_const(CONST_LG2);
  1642. }
  1643.  
  1644. static void fldln2()
  1645. {
  1646.   fld_const(CONST_LN2);
  1647. }
  1648.  
  1649. static void fldz()
  1650. {
  1651.   fld_const(CONST_Z);
  1652. }
  1653.  
  1654. static FUNC emu_15_table[] = {
  1655.   fld1, fldl2t, fldl2e, fldpi, fldlg2, fldln2, fldz, emu_bad
  1656. };
  1657.  
  1658. static void emu_15()
  1659. {
  1660.   if (modrm > 0277)
  1661.   {
  1662.     (emu_15_table[modrm&7])();
  1663.   }
  1664.   else
  1665.   {
  1666.     // fldcw
  1667.     control_word = *(short *)get_modrm();
  1668.   }
  1669. }
  1670.  
  1671. static void f2xm1()
  1672. {
  1673.   if (empty())
  1674.     return;
  1675.   reg xloga, val, rv, bottom, tmp;
  1676.   long i;
  1677.  
  1678.   r_mul(CONST_LN2, st(), xloga);
  1679.   val = xloga;
  1680.   rv = xloga;
  1681.  
  1682.   for (i=2; i<16; i++)
  1683.   {
  1684.     r_mov(&i, bottom);
  1685.     r_mul(val, xloga, tmp);
  1686.     r_div(tmp, bottom, val);
  1687.     r_add(val, rv, tmp);
  1688.     rv = tmp;
  1689.   }
  1690.   st() = rv;
  1691. }
  1692.  
  1693. // logb(x) = loga(x) / loga(b)
  1694. // log2(x) = loge(x) / loge(2)
  1695.  
  1696. static void fyl2x()
  1697. {
  1698.   if (empty())
  1699.     return;
  1700.   reg z, x, nom, denom, xsquare, term, temp, sum, pow;
  1701.   long exponent;
  1702.   reg CONST_SQRT2 = { SIGN_POS, TW_V, EXP_BIAS, 0xf9de6000, 0xb504f333 };
  1703.  
  1704.   z = st();
  1705.   if ((z.tag != TW_V) || (z.sign != SIGN_POS)) {
  1706.     return exception(EX_I); // not valid, zero or negative
  1707.   }  
  1708.   exponent = (long)(z.exp - EXP_BIAS);
  1709.   z.exp=EXP_BIAS;
  1710.   if (compare(z, CONST_SQRT2) == COMP_A_GT_B) {
  1711.     (z.exp)--;
  1712.     exponent++;
  1713.   }
  1714.  
  1715.   r_sub(z, CONST_1, nom);
  1716.   r_add(z, CONST_1, denom);
  1717.   r_div(nom, denom, x);
  1718.   pow = x;
  1719.   sum = x;
  1720.   r_mul(x, x, xsquare);
  1721.   
  1722.   for (long i=3; i<25; i+=2)
  1723.   {
  1724.     r_mul(pow, xsquare, temp);
  1725.     pow = temp;
  1726.  
  1727.     r_mov(&i, denom);
  1728.     r_div(pow, denom, term);
  1729.  
  1730.     r_add(term, sum, temp);
  1731.     sum = temp;
  1732.   }
  1733.   r_div(sum, CONST_LN2, temp);
  1734.   temp.exp++;
  1735.   if (exponent) {
  1736.     r_mov(&exponent, term);
  1737.     r_add(term, temp, sum);
  1738.   } else {
  1739.     sum = temp;
  1740.   }
  1741.  
  1742.   r_mul(sum, st(1), temp);
  1743.   st(1) = temp;
  1744.   st().tag = TW_E;
  1745.   top++;
  1746. }
  1747.  
  1748. static int fprem_do(reg& quot, reg& div1, int round) // remainder of st() / st(1)
  1749. {
  1750.   int rv;
  1751.   int old_cw = control_word;
  1752.   control_word &= ~CW_RC;
  1753.   control_word |= round;
  1754.   int expdif = quot.exp - div1.exp;
  1755.   if (expdif < 64)
  1756.   {
  1757.     reg tmp, tmp2;
  1758.     r_div(quot, div1, tmp);
  1759.     long q;
  1760.     r_mov(tmp, &q);
  1761.     r_mov(&q, tmp);
  1762.     r_mul(div1, tmp, tmp2);
  1763.     r_sub(quot, tmp2, tmp);
  1764.     quot = tmp;
  1765.     rv = q & 7;
  1766.   }
  1767.   else
  1768.   {
  1769.     reg tmp, tmp2;
  1770.     setcc(SW_C2);
  1771.     r_div(st(), div1, tmp);
  1772.     int old_exp = tmp.exp;
  1773.     tmp.exp &= 31;
  1774.     long q;
  1775.     r_mov(tmp, &q);
  1776.     r_mov(&q, tmp);
  1777.     tmp.exp = old_exp;
  1778.     r_mul(div1, tmp, tmp2);
  1779.     r_sub(quot, tmp2, tmp);
  1780.     quot = tmp;
  1781.     rv = -1;
  1782.   }
  1783.   control_word = old_cw;
  1784.   return rv;;
  1785. }
  1786.  
  1787. static void fsincos()
  1788. {
  1789.   if (empty())
  1790.     return;
  1791.   int q = fprem_do(st(), CONST_PI2, RC_CHOP);
  1792.  
  1793.   if (q & 1)
  1794.   {
  1795.     reg tmp;
  1796.     r_sub(CONST_PI2, st(), tmp);
  1797.     st() = tmp;
  1798.   }
  1799.  
  1800.   reg x2, val, rv, tmp, t2;
  1801.   reg valc, rvc, tmpc;
  1802.   val = st();
  1803.   r_mul(st(), val, x2);
  1804.   rv = val;
  1805.   valc = CONST_1;
  1806.   rvc = valc;
  1807.  
  1808.  
  1809.   for (int i=0; i<11; i++)
  1810.   {
  1811.     val.sign ^= SIGN_POS ^ SIGN_NEG;
  1812.     valc.sign ^= SIGN_POS ^ SIGN_NEG;
  1813.     r_mul(x2, val, tmp);
  1814.     r_mul(x2, valc, tmpc);
  1815.     long c = ((i<<1)+2) * ((i<<1)+3);
  1816.     r_mov(&c, t2);
  1817.     r_div(tmp, t2, val);
  1818.     c = ((i<<1)+1) * ((i<<1)+2);
  1819.     r_mov(&c, t2);
  1820.     r_div(tmpc, t2, valc);
  1821.     r_add(val, rv, tmp);
  1822.     rv = tmp;
  1823.     r_add(valc, rvc, tmpc);
  1824.     rvc = tmpc;
  1825.   }
  1826.   setcc(0);
  1827.  
  1828.   if (q & 2)
  1829.     rv.sign ^= SIGN_POS ^ SIGN_NEG;
  1830.   st() = rv;
  1831.  
  1832.   top--;
  1833.   register int qq = q & 3;
  1834.   if ((qq == 1) || (qq == 2))
  1835.     rvc.sign ^= SIGN_POS ^ SIGN_NEG;
  1836.   st() = rvc;
  1837. }
  1838.  
  1839. static void fptan()
  1840. {
  1841.   fsincos();
  1842.   if (empty(1))
  1843.     return;
  1844.   reg tmp;
  1845.   r_div(st(1), st(), tmp);
  1846.   st(1) = tmp;
  1847.   st() = CONST_1;
  1848. }
  1849.  
  1850. static void fpatan()
  1851. {
  1852.   if (empty(1))
  1853.     return;
  1854.   if (is_zero(st()))
  1855.   {
  1856.     st(1) = CONST_PI2;
  1857.     st().tag = TW_E;
  1858.     top++;
  1859.     return;
  1860.   }
  1861.   if (is_zero(st(1)))
  1862.   {
  1863.     st(1) = CONST_Z;
  1864.     st().tag = TW_E;
  1865.     top++;
  1866.     return;
  1867.   }
  1868.   reg x2, sum, term, pow, temp;
  1869.   int quadrant = 0;
  1870.   if (st(1).sign == SIGN_NEG)
  1871.     quadrant |= 1;
  1872.   if (st(0).sign == SIGN_NEG)
  1873.     quadrant |= 2;
  1874.   st(1).sign = st().sign = SIGN_POS;
  1875.   if (compare(st(1), st()) == COMP_A_GT_B)
  1876.   {
  1877.     quadrant |= 4;
  1878.     temp = st(1);
  1879.     st(1) = st();
  1880.     st() = temp;
  1881.   }
  1882.  
  1883.   r_div(st(1), st(), sum);
  1884.   r_mul(sum, sum, x2);
  1885.   pow = sum;
  1886.  
  1887.   x2.sign ^= SIGN_POS^SIGN_NEG;
  1888.  
  1889.   for (long i=3; i<25; i+=2)
  1890.   {
  1891.     r_mul(pow, x2, temp);
  1892.     pow = temp;
  1893.     r_mov(&i, temp);
  1894.     r_div(pow, temp, term);
  1895.     r_add(sum, term, temp);
  1896.     sum = temp;
  1897.   }
  1898.  
  1899.   if (quadrant & 4)
  1900.   {
  1901.     r_sub(CONST_PI2, sum, temp);
  1902.     sum = temp;
  1903.   }
  1904.   if (quadrant & 2)
  1905.   {
  1906.     r_sub(CONST_PI, sum, temp);
  1907.     sum = temp;
  1908.   }
  1909.   if (quadrant & 1)
  1910.     sum.sign ^= SIGN_POS^SIGN_NEG;
  1911.  
  1912.   st(1) = sum;
  1913.   st().tag = TW_E;
  1914.   top++;
  1915. }
  1916.  
  1917. static void fxtract()
  1918. {
  1919.   if (empty())
  1920.     return;
  1921.   if (full())
  1922.     return;
  1923.   top--;
  1924.   st() = st(1);
  1925.   st().exp = EXP_BIAS;
  1926.   long e = st(1).exp - EXP_BIAS;
  1927.   r_mov(&e, st(1));
  1928. }
  1929.  
  1930. static void fprem1()
  1931. {
  1932.   if (empty(1))
  1933.     return;
  1934.   int q = fprem_do(st(), st(1), RC_RND);
  1935.   if (q == -1)
  1936.     setcc(SW_C2);
  1937.   else
  1938.   {
  1939.     int c = 0;
  1940.     if (q&4) c |= SW_C3;
  1941.     if (q&2) c |= SW_C1;
  1942.     if (q&1) c |= SW_C0;
  1943.     setcc(c);
  1944.   }
  1945. }
  1946.  
  1947. static void fdecstp()
  1948. {
  1949.   top--;
  1950. }
  1951.  
  1952. static void fincstp()
  1953. {
  1954.   top++;
  1955. }
  1956.  
  1957. static FUNC emu_16_table[] = {
  1958.   f2xm1, fyl2x, fptan, fpatan, fxtract, fprem1, fdecstp, fincstp
  1959. };
  1960.  
  1961. static void emu_16()
  1962. {
  1963.   if (modrm > 0277)
  1964.   {
  1965.     (emu_16_table[modrm&7])();
  1966.   }
  1967.   else
  1968.   {
  1969.     emu_bad();
  1970.   }
  1971. }
  1972.  
  1973. static void fprem()
  1974. {
  1975.   if (empty(1))
  1976.     return;
  1977.   int q = fprem_do(st(), st(1), RC_CHOP);
  1978.   if (q == -1)
  1979.     setcc(SW_C2);
  1980.   else
  1981.   {
  1982.     int c = 0;
  1983.     if (q&4) c |= SW_C3;
  1984.     if (q&2) c |= SW_C1;
  1985.     if (q&1) c |= SW_C0;
  1986.     setcc(c);
  1987.   }
  1988. }
  1989.  
  1990. void fyl2x();
  1991.  
  1992. static void fyl2xp1()
  1993. {
  1994.   reg newx;
  1995.   r_add(st(), CONST_1, newx);
  1996.   st() = newx;
  1997.   fyl2x();
  1998. }
  1999.  
  2000. static void fsqrt()
  2001. {
  2002.   if (empty())
  2003.     return;
  2004.   if (st().tag == TW_Z)
  2005.     return;
  2006.   if (st().exp == EXP_MAX)
  2007.     return;
  2008.   if (st().sign == SIGN_NEG)
  2009.     return exception(EX_I);
  2010.  
  2011.   unsigned long long val = *(unsigned long long *)(&st().sigl);
  2012.   unsigned long long result = 0;
  2013.   unsigned long long side = 0;
  2014.   unsigned long long left = 0;
  2015.   if (st().exp & 1)
  2016.   {
  2017.     djshrd(&val);
  2018.     st().exp++;
  2019.   }
  2020.   int exp = (st().exp - EXP_BIAS - 1)/2 - 64;
  2021.   while (!(((long *)&result)[1] & 0x80000000))
  2022.   {
  2023.     left = (left << 2) + (((unsigned *)&val)[1] >> 30);
  2024.     djshld(&val);
  2025.     djshld(&val);
  2026.     if (left >= side*2 + 1)
  2027.     {
  2028.       left -= side*2+1;
  2029.       side = (side+1)*2;
  2030.       djshld(&result);
  2031.       result |= 1;
  2032.     }
  2033.     else
  2034.     {
  2035.       side *= 2;
  2036.       djshld(&result);
  2037.     }
  2038.     exp++;
  2039.   }
  2040.   st().exp = exp + EXP_BIAS;
  2041.   st().sigl = result & 0xffffffff;
  2042.   st().sigh = result >> 32;
  2043.   st().tag = TW_V;
  2044. }
  2045.  
  2046. static void frndint()
  2047. {
  2048.   if (empty())
  2049.     return;
  2050.   long long tmp;
  2051.   if (st().exp > EXP_BIAS+62)
  2052.     return;
  2053.   r_mov(st(), &tmp);
  2054.   r_mov(&tmp, st());
  2055. }
  2056.  
  2057. static void fscale()
  2058. {
  2059.   long scale1;
  2060.   if (empty(1))
  2061.     return;
  2062.   r_mov(st(1), &scale1);
  2063.   st().exp += scale1;
  2064. }
  2065.  
  2066. static void fsin()
  2067. {
  2068.   if (empty())
  2069.     return;
  2070.   int q = fprem_do(st(), CONST_PI2, RC_CHOP);
  2071.  
  2072.   if (q & 1)
  2073.   {
  2074.     reg tmp;
  2075.     r_sub(CONST_PI2, st(), tmp);
  2076.     st() = tmp;
  2077.   }
  2078.  
  2079.   reg x2, val, rv, tmp, t2;
  2080.   val = st();
  2081.   r_mul(st(), val, x2);
  2082.   rv = val;
  2083.  
  2084.  
  2085.   for (int i=0; i<11; i++)
  2086.   {
  2087.     long c = ((i<<1)+2) * ((i<<1)+3);
  2088.     val.sign ^= SIGN_POS ^ SIGN_NEG;
  2089.     r_mul(x2, val, tmp);
  2090.     r_mov(&c, t2);
  2091.     r_div(tmp, t2, val);
  2092.     r_add(val, rv, tmp);
  2093.     rv = tmp;
  2094.   }
  2095.   setcc(0);
  2096.   if (q & 2)
  2097.     rv.sign ^= SIGN_POS ^ SIGN_NEG;
  2098.   st() = rv;
  2099. }
  2100.  
  2101. static void fcos()
  2102. {
  2103.   if (empty())
  2104.     return;
  2105.   int q = fprem_do(st(), CONST_PI2, RC_CHOP);
  2106.  
  2107.   if (q & 1)
  2108.   {
  2109.     reg tmp;
  2110.     r_sub(CONST_PI2, st(), tmp);
  2111.     st() = tmp;
  2112.   }
  2113.  
  2114.   reg x2, val, rv, tmp, t2;
  2115.   val = st();
  2116.   r_mul(st(), val, x2);
  2117.   val = CONST_1;
  2118.   rv = val;
  2119.  
  2120.  
  2121.   for (int i=0; i<11; i++)
  2122.   {
  2123.     long c = ((i<<1)+1) * ((i<<1)+2);
  2124.     val.sign ^= SIGN_POS ^ SIGN_NEG;
  2125.     r_mul(x2, val, tmp);
  2126.     r_mov(&c, t2);
  2127.     r_div(tmp, t2, val);
  2128.     r_add(val, rv, tmp);
  2129.     rv = tmp;
  2130.   }
  2131.   setcc(0);
  2132.   register int qq = q & 3;
  2133.   if ((qq == 1) || (qq == 2))
  2134.     rv.sign ^= SIGN_POS ^ SIGN_NEG;
  2135.   st() = rv;
  2136. }
  2137.  
  2138. static FUNC emu_17_table[] = {
  2139.   fprem, fyl2xp1, fsqrt, fsincos, frndint, fscale, fsin, fcos
  2140. };
  2141.  
  2142. static void emu_17()
  2143. {
  2144.   if (modrm > 0277)
  2145.   {
  2146.     (emu_17_table[modrm&7])();
  2147.   }
  2148.   else
  2149.   {
  2150.     // fstcw m16int
  2151.     *(short *)get_modrm() = control_word;
  2152.   }
  2153. }
  2154.  
  2155. static void emu_20()
  2156. {
  2157.   if (empty())
  2158.     return;
  2159.   if (modrm > 0277)
  2160.   {
  2161.     emu_bad();
  2162.   }
  2163.   else
  2164.   {
  2165.     // fiadd m32int
  2166.     reg t1, t2;
  2167.     r_mov((long *)get_modrm(), t1);
  2168.     r_add(st(), t1, t2);
  2169.     st() = t2;
  2170.   }
  2171. }
  2172.  
  2173. static void emu_21()
  2174. {
  2175.   if (empty())
  2176.     return;
  2177.   if (modrm > 0277)
  2178.   {
  2179.     //
  2180.     emu_bad();
  2181.   }
  2182.   else
  2183.   {
  2184.     // fimul m32int
  2185.     reg t, t2;
  2186.     r_mov((long *)get_modrm(), t);
  2187.     r_mul(st(), t, t2);
  2188.     st() = t2;
  2189.   }
  2190. }
  2191.  
  2192. static void emu_22()
  2193. {
  2194.   if (empty())
  2195.     return;
  2196.   if (modrm > 0277)
  2197.   {
  2198.     emu_bad();
  2199.   }
  2200.   else
  2201.   {
  2202.     // ficom m32int
  2203.     reg t;
  2204.     r_mov((long *)get_modrm(), t);
  2205.     int c = compare(st(), t);
  2206.     int f;
  2207.     if (c & COMP_NAN)
  2208.     {
  2209.       exception(EX_I);
  2210.       f = SW_C3 | SW_C2 | SW_C0;
  2211.     }
  2212.     else
  2213.       switch (c)
  2214.       {
  2215.         case COMP_A_LT_B:
  2216.           f = SW_C0;
  2217.           break;
  2218.         case COMP_A_EQ_B:
  2219.           f = SW_C3;
  2220.           break;
  2221.         case COMP_A_GT_B:
  2222.           f = 0;
  2223.           break;
  2224.         case COMP_NOCOMP:
  2225.           f = SW_C3 | SW_C2 | SW_C0;
  2226.           break;
  2227.       }
  2228.     setcc(f);
  2229.   }
  2230. }
  2231.  
  2232. static void emu_23()
  2233. {
  2234.   if (empty())
  2235.     return;
  2236.   if (modrm > 0277)
  2237.   {
  2238.     emu_bad();
  2239.   }
  2240.   else
  2241.   {
  2242.     // ficomp m32int
  2243.     reg t;
  2244.     r_mov((long *)get_modrm(), t);
  2245.     int c = compare(st(), t);
  2246.     st().tag = TW_E;
  2247.     top++;
  2248.     int f;
  2249.     if (c & COMP_NAN)
  2250.     {
  2251.       exception(EX_I);
  2252.       f = SW_C3 | SW_C2 | SW_C0;
  2253.     }
  2254.     else
  2255.       switch (c)
  2256.       {
  2257.         case COMP_A_LT_B:
  2258.           f = SW_C0;
  2259.           break;
  2260.         case COMP_A_EQ_B:
  2261.           f = SW_C3;
  2262.           break;
  2263.         case COMP_A_GT_B:
  2264.           f = 0;
  2265.           break;
  2266.         case COMP_NOCOMP:
  2267.           f = SW_C3 | SW_C2 | SW_C0;
  2268.           break;
  2269.       }
  2270.     setcc(f);
  2271.   }
  2272. }
  2273.  
  2274. static void emu_24()
  2275. {
  2276.   if (empty())
  2277.     return;
  2278.   if (modrm > 0277)
  2279.   {
  2280.     emu_bad();
  2281.   }
  2282.   else
  2283.   {
  2284.     // fisub m32int
  2285.     reg t1, t2;
  2286.     r_mov((long *)get_modrm(), t1);
  2287.     r_sub(st(), t1, t2);
  2288.     st() = t2;
  2289.   }
  2290. }
  2291.  
  2292. static void emu_25()
  2293. {
  2294.   if (empty())
  2295.     return;
  2296.   if (modrm > 0277)
  2297.   {
  2298.     // fucompp
  2299.     if ((modrm&7) != 1)
  2300.       emu_bad();
  2301.     else
  2302.     {
  2303.     if (empty(modrm&7))
  2304.     {
  2305.       setcc(SW_C3|SW_C2|SW_C0);
  2306.       return;
  2307.     }
  2308.     int c = compare(st(), st(1));
  2309.     st().tag = TW_E;
  2310.     top++;
  2311.     st().tag = TW_E;
  2312.     top++;
  2313.     int f;
  2314.     if (c & COMP_SNAN)
  2315.     {
  2316.       exception(EX_I);
  2317.       f = SW_C3 | SW_C2 | SW_C0;
  2318.     }
  2319.     else
  2320.       switch (c)
  2321.       {
  2322.         case COMP_A_LT_B:
  2323.           f = SW_C0;
  2324.           break;
  2325.         case COMP_A_EQ_B:
  2326.           f = SW_C3;
  2327.           break;
  2328.         case COMP_A_GT_B:
  2329.           f = 0;
  2330.           break;
  2331.         case COMP_NOCOMP:
  2332.           f = SW_C3 | SW_C2 | SW_C0;
  2333.           break;
  2334.       }
  2335.     setcc(f);
  2336.     }
  2337.   }
  2338.   else
  2339.   {
  2340.     // fisubr m32int
  2341.     reg t1, t2;
  2342.     r_mov((long *)get_modrm(), t1);
  2343.     r_sub(t1, st(), t2);
  2344.     st() = t2;
  2345.   }
  2346. }
  2347.  
  2348. static void emu_26()
  2349. {
  2350.   if (empty())
  2351.     return;
  2352.   if (modrm > 0277)
  2353.   {
  2354.     //
  2355.     emu_bad();
  2356.   }
  2357.   else
  2358.   {
  2359.     // fidiv m32int
  2360.     reg t, t2;
  2361.     r_mov((long *)get_modrm(), t);
  2362.     r_div(st(), t, t2);
  2363.     st() = t2;
  2364.   }
  2365. }
  2366.  
  2367. static void emu_27()
  2368. {
  2369.   if (empty())
  2370.     return;
  2371.   if (modrm > 0277)
  2372.   {
  2373.     //
  2374.     emu_bad();
  2375.   }
  2376.   else
  2377.   {
  2378.     // fidivr m32int
  2379.     reg t, t2;
  2380.     r_mov((long *)get_modrm(), t);
  2381.     r_div(t, st(), t2);
  2382.     st() = t2;
  2383.   }
  2384. }
  2385.  
  2386. static void emu_30()
  2387. {
  2388.   if (full())
  2389.     return;
  2390.   if (modrm > 0277)
  2391.   {
  2392.     emu_bad();
  2393.   }
  2394.   else
  2395.   {
  2396.     // fild m32int
  2397.     top--;
  2398.     r_mov((long *)get_modrm(), st());
  2399.   }
  2400. }
  2401.  
  2402. static void emu_31()
  2403. {
  2404.   void emu_bad();
  2405.   emu_bad();
  2406. }
  2407.  
  2408. static void emu_32()
  2409. {
  2410.   if (empty())
  2411.     return;
  2412.   if (modrm > 0277)
  2413.   {
  2414.     //
  2415.     emu_bad();
  2416.   }
  2417.   else
  2418.   {
  2419.     // fist m32int
  2420.     r_mov(st(), (long *)get_modrm());
  2421.   }
  2422. }
  2423.  
  2424. static void emu_33()
  2425. {
  2426.   if (empty())
  2427.     return;
  2428.   if (modrm > 0277)
  2429.   {
  2430.     //
  2431.     emu_bad();
  2432.   }
  2433.   else
  2434.   {
  2435.     // fistp m32int
  2436.     r_mov(st(), (long *)get_modrm());
  2437.     st().tag = TW_E;
  2438.     top++;
  2439.   }
  2440. }
  2441.  
  2442. static void fclex()
  2443. {
  2444.   status_word &= ~(SW_B|SW_ES|SW_SF|SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE);
  2445. }
  2446.  
  2447. static void finit()
  2448. {
  2449.   control_word = 0x037e;
  2450.   status_word = 0;
  2451.   top = 0;
  2452.   for (int r=0; r<8; r++)
  2453.   {
  2454.     regs[r].sign = 0;
  2455.     regs[r].tag = TW_E;
  2456.     regs[r].exp = 0;
  2457.     regs[r].sigh = 0;
  2458.     regs[r].sigl = 0;
  2459.   }
  2460. }
  2461.  
  2462. static FUNC emu_34_table[] = {
  2463.   emu_bad, emu_bad, fclex, finit, emu_bad, emu_bad, emu_bad, emu_bad
  2464. };
  2465.  
  2466. static void emu_34()
  2467. {
  2468.   if (modrm > 0277)
  2469.   {
  2470.     (emu_34_table[modrm&7])();
  2471.   }
  2472.   else
  2473.   {
  2474.     //
  2475.     emu_bad();
  2476.   }
  2477. }
  2478.  
  2479. static void emu_35()
  2480. {
  2481.   if (full())
  2482.     return;
  2483.   if (modrm > 0277)
  2484.   {
  2485.     emu_bad();
  2486.   }
  2487.   else
  2488.   {
  2489.     // fld m80real
  2490.     top--;
  2491.     r_mov((long double *)get_modrm(), st());
  2492.   }
  2493. }
  2494.  
  2495. static void emu_36()
  2496. {
  2497.   void emu_bad();
  2498.   emu_bad();
  2499. }
  2500.  
  2501. static void emu_37()
  2502. {
  2503.   if (modrm > 0277)
  2504.   {
  2505.     emu_bad();
  2506.   }
  2507.   else
  2508.   {
  2509.     // fstp m80real
  2510.     if (empty())
  2511.       return;
  2512.     r_mov(st(), (long double *)get_modrm());
  2513.     st().tag = TW_E;
  2514.     top++;
  2515.   }
  2516. }
  2517.  
  2518. static void emu_40()
  2519. {
  2520.   if (empty())
  2521.     return;
  2522.   if (modrm > 0277)
  2523.   {
  2524.     // fadd st(i),st
  2525.     int i = modrm & 7;
  2526.     if (empty(i))
  2527.       return;
  2528.     reg tmp;
  2529.     r_add(st(), st(i), tmp);
  2530.     st(i) = tmp;
  2531.     return;
  2532.   }
  2533.   else
  2534.   {
  2535.     // fadd m64real
  2536.     reg t1, t2;
  2537.     r_mov((double *)get_modrm(), t1);
  2538.     r_add(t1, st(), t2);
  2539.     st() = t2;
  2540.   }
  2541. }
  2542.  
  2543. static void emu_41()
  2544. {
  2545.   if (empty())
  2546.     return;
  2547.   if (modrm > 0277)
  2548.   {
  2549.     // fmul st(i),st
  2550.     int i = modrm & 7;
  2551.     if (empty(i))
  2552.       return;
  2553.     reg t;
  2554.     r_mul(st(i), st(), t);
  2555.     st(i) = t;
  2556.   }
  2557.   else
  2558.   {
  2559.     // fmul m64real
  2560.     reg t, t2;
  2561.     r_mov((double *)get_modrm(), t);
  2562.     r_mul(st(), t, t2);
  2563.     st() = t2;
  2564.   }
  2565. }
  2566.  
  2567. static void emu_42()
  2568. {
  2569.   if (empty())
  2570.     return;
  2571.   if (modrm > 0277)
  2572.   {
  2573.     // 
  2574.     emu_bad();
  2575.   }
  2576.   else
  2577.   {
  2578.     // fcom m64real
  2579.     reg t;
  2580.     r_mov((double *)get_modrm(), t);
  2581.     int c = compare(st(), t);
  2582.     int f;
  2583.     if (c & COMP_NAN)
  2584.     {
  2585.       exception(EX_I);
  2586.       f = SW_C3 | SW_C2 | SW_C0;
  2587.     }
  2588.     else
  2589.       switch (c)
  2590.       {
  2591.         case COMP_A_LT_B:
  2592.           f = SW_C0;
  2593.           break;
  2594.         case COMP_A_EQ_B:
  2595.           f = SW_C3;
  2596.           break;
  2597.         case COMP_A_GT_B:
  2598.           f = 0;
  2599.           break;
  2600.         case COMP_NOCOMP:
  2601.           f = SW_C3 | SW_C2 | SW_C0;
  2602.           break;
  2603.       }
  2604.     setcc(f);
  2605.   }
  2606. }
  2607.  
  2608. static void emu_43()
  2609. {
  2610.   if (empty())
  2611.     return;
  2612.   if (modrm > 0277)
  2613.   {
  2614.     emu_bad();
  2615.   }
  2616.   else
  2617.   {
  2618.     // fcomp m64real
  2619.     reg t;
  2620.     r_mov((double *)get_modrm(), t);
  2621.     int c = compare(st(), t);
  2622.     st().tag = TW_E;
  2623.     top++;
  2624.     int f;
  2625.     if (c & COMP_NAN)
  2626.     {
  2627.       exception(EX_I);
  2628.       f = SW_C3 | SW_C2 | SW_C0;
  2629.     }
  2630.     else
  2631.       switch (c)
  2632.       {
  2633.         case COMP_A_LT_B:
  2634.           f = SW_C0;
  2635.           break;
  2636.         case COMP_A_EQ_B:
  2637.           f = SW_C3;
  2638.           break;
  2639.         case COMP_A_GT_B:
  2640.           f = 0;
  2641.           break;
  2642.         case COMP_NOCOMP:
  2643.           f = SW_C3 | SW_C2 | SW_C0;
  2644.           break;
  2645.       }
  2646.     setcc(f);
  2647.   }
  2648. }
  2649.  
  2650. static void emu_44()
  2651. {
  2652.   if (empty())
  2653.     return;
  2654.   if (modrm > 0277)
  2655.   {
  2656.     // fsub st(i),st
  2657.     int i = modrm & 7;
  2658.     if (empty(i))
  2659.       return;
  2660.     reg tmp;
  2661.     r_sub(st(), st(i), tmp);
  2662.     st(i) = tmp;
  2663.     return;
  2664.   }
  2665.   else
  2666.   {
  2667.     // fsub m64real
  2668.     reg t1, t2;
  2669.     r_mov((double *)get_modrm(), t1);
  2670.     r_sub(st(), t1, t2);
  2671.     st() = t2;
  2672.   }
  2673. }
  2674.  
  2675. static void emu_45()
  2676. {
  2677.   if (empty())
  2678.     return;
  2679.   if (modrm > 0277)
  2680.   {
  2681.     // fsubr st(i),st
  2682.     int i = modrm & 7;
  2683.     if (empty(i))
  2684.       return;
  2685.     reg tmp;
  2686.     r_sub(st(i), st(), tmp);
  2687.     st(i) = tmp;
  2688.     return;
  2689.   }
  2690.   else
  2691.   {
  2692.     // fsubr m64real
  2693.     reg t1, t2;
  2694.     r_mov((double *)get_modrm(), t1);
  2695.     r_sub(t1, st(), t2);
  2696.     st() = t2;
  2697.   }
  2698. }
  2699.  
  2700. static void emu_46()
  2701. {
  2702.   if (empty())
  2703.     return;
  2704.   if (modrm > 0277)
  2705.   {
  2706.     // fdivr st(i),st
  2707.     int i = modrm&7;
  2708.     if (empty(i))
  2709.       return;
  2710.     reg t;
  2711.     r_div(st(), st(i), t);
  2712.     st(i) = t;
  2713.   }
  2714.   else
  2715.   {
  2716.     // fdiv m64real
  2717.     reg t, t2;
  2718.     r_mov((double *)get_modrm(), t);
  2719.     r_div(st(), t, t2);
  2720.     st() = t2;
  2721.   }
  2722. }
  2723.  
  2724. static void emu_47()
  2725. {
  2726.   if (empty())
  2727.     return;
  2728.   if (modrm > 0277)
  2729.   {
  2730.     // fdiv st(i),st
  2731.     reg t;
  2732.     int i = modrm & 7;
  2733.     if (empty(i))
  2734.       return;
  2735.     r_div(st(i), st(0), t);
  2736.     st(i) = t;
  2737.   }
  2738.   else
  2739.   {
  2740.     // fdivr m64real
  2741.     reg t, t2;
  2742.     r_mov((double *)get_modrm(), t);
  2743.     r_div(t, st(), t2);
  2744.     st() = t2;
  2745.   }
  2746. }
  2747.  
  2748. static void emu_50()
  2749. {
  2750.   if (full())
  2751.     return;
  2752.   if (modrm > 0277)
  2753.   {
  2754.     // ffree st(i)
  2755.     int i = modrm & 7;
  2756.     st(i).tag = TW_E;
  2757.   }
  2758.   else
  2759.   {
  2760.     // fld m64real
  2761.     top--;
  2762.     r_mov((double *)get_modrm(), st());
  2763.   }
  2764. }
  2765.  
  2766. static void emu_51()
  2767. {
  2768.   void emu_bad();
  2769.   emu_bad();
  2770. }
  2771.  
  2772. static void emu_52()
  2773. {
  2774.   if (modrm > 0277)
  2775.   {
  2776.     st(modrm&7) = st();
  2777.   }
  2778.   else
  2779.   {
  2780.     // fst m64real
  2781.     if (empty())
  2782.       return;
  2783.     r_mov(st(), (double *)get_modrm());
  2784.   }
  2785. }
  2786.  
  2787. static void emu_53()
  2788. {
  2789.   if (modrm > 0277)
  2790.   {
  2791.     // fstp st(i)
  2792.     st(modrm&7) = st();
  2793.     st().tag = TW_E;
  2794.     top++;
  2795.   }
  2796.   else
  2797.   {
  2798.     // fstp m64real
  2799.     if (empty())
  2800.       return;
  2801.     r_mov(st(), (double *)get_modrm());
  2802.     st().tag = TW_E;
  2803.     top++;
  2804.   }
  2805. }
  2806.  
  2807. static void emu_54()
  2808. {
  2809.   if (modrm > 0277)
  2810.   {
  2811.     // fucom st(i)
  2812.     if (empty())
  2813.       return;
  2814.     if (empty(modrm&7))
  2815.     {
  2816.       setcc(SW_C3|SW_C2|SW_C0);
  2817.       return;
  2818.     }
  2819.     int c = compare(st(), st(modrm&7));
  2820.     int f;
  2821.     if (c & COMP_SNAN)
  2822.     {
  2823.       exception(EX_I);
  2824.       f = SW_C3 | SW_C2 | SW_C0;
  2825.     }
  2826.     else
  2827.       switch (c)
  2828.       {
  2829.         case COMP_A_LT_B:
  2830.           f = SW_C0;
  2831.           break;
  2832.         case COMP_A_EQ_B:
  2833.           f = SW_C3;
  2834.           break;
  2835.         case COMP_A_GT_B:
  2836.           f = 0;
  2837.           break;
  2838.         case COMP_NOCOMP:
  2839.           f = SW_C3 | SW_C2 | SW_C0;
  2840.           break;
  2841.       }
  2842.     setcc(f);
  2843.     
  2844.   }
  2845.   else
  2846.   {
  2847.     // frestor
  2848.     void *addr = get_modrm();
  2849.     int i, tag_word;
  2850.  
  2851.     control_word = *(int *)(addr+0) & 0xffff;
  2852.     status_word = *(int *)(addr+4) & 0xffff;
  2853.     tag_word = *(int *)(addr+8) & 0xffff;
  2854.     top = (status_word / SW_TOPS) & 3;
  2855.     for (i=0; i<8; i++)
  2856.     {
  2857.       r_mov((long double *)(addr + 0x1c + 10), st(i));
  2858.       st(i).tag = (tag_word >> (((i+top)&7)*2)) & 3;
  2859.     }
  2860.   }
  2861. }
  2862.  
  2863. static void emu_55()
  2864. {
  2865.   if (empty())
  2866.     return;
  2867.   if (modrm > 0277)
  2868.   {
  2869.     // fucomp st(i)
  2870.     if (empty(modrm&7))
  2871.     {
  2872.       setcc(SW_C3|SW_C2|SW_C0);
  2873.       return;
  2874.     }
  2875.     int c = compare(st(), st(modrm&7));
  2876.     st().tag = TW_E;
  2877.     top++;
  2878.     int f;
  2879.     if (c & COMP_SNAN)
  2880.     {
  2881.       exception(EX_I);
  2882.       f = SW_C3 | SW_C2 | SW_C0;
  2883.     }
  2884.     else
  2885.       switch (c)
  2886.       {
  2887.         case COMP_A_LT_B:
  2888.           f = SW_C0;
  2889.           break;
  2890.         case COMP_A_EQ_B:
  2891.           f = SW_C3;
  2892.           break;
  2893.         case COMP_A_GT_B:
  2894.           f = 0;
  2895.           break;
  2896.         case COMP_NOCOMP:
  2897.           f = SW_C3 | SW_C2 | SW_C0;
  2898.           break;
  2899.       }
  2900.     setcc(f);
  2901.     
  2902.   }
  2903.   else
  2904.   {
  2905.     emu_bad();
  2906.   }
  2907. }
  2908.  
  2909. static void emu_56() /* fsave */
  2910. {
  2911.   void *addr = get_modrm();
  2912.   int i, tag_word=0;
  2913.  
  2914.   status_word = status_word & ~SW_TOP;
  2915.   status_word += (top&7) * SW_TOPS;
  2916.  
  2917.   *(int *)(addr+0) = control_word & 0xffff;
  2918.   *(int *)(addr+4) = status_word & 0xffff;
  2919.   for (i=0; i<8; i++)
  2920.   {
  2921.     tag_word |= (st(i).tag << (((i+top)&7)*2));
  2922.     r_mov(st(i), (long double *)(addr + 0x1c + i*10));
  2923.   }
  2924.   *(int *)(addr+8) = tag_word & 0xffff;
  2925. }
  2926.  
  2927. static void emu_57()
  2928. {
  2929.   if (modrm > 0277)
  2930.   {
  2931.     //
  2932.     emu_bad();
  2933.   }
  2934.   else
  2935.   {
  2936.     // fstsw m2byte
  2937.     status_word &= ~SW_TOP;
  2938.     status_word |= (top&7) * SW_TOPS;
  2939.     *(short *)get_modrm() = status_word;
  2940.   }
  2941. }
  2942.  
  2943. static void emu_60()
  2944. {
  2945.   if (empty())
  2946.     return;
  2947.   if (modrm > 0277)
  2948.   {
  2949.     // faddp st(i),st
  2950.     int i = modrm & 7;
  2951.     if (empty(i))
  2952.       return;
  2953.     reg tmp;
  2954.     r_add(st(), st(i), tmp);
  2955.     st(i) = tmp;
  2956.     st().tag = TW_E;
  2957.     top++;
  2958.     return;
  2959.   }
  2960.   else
  2961.   {
  2962.     // fiadd m16int
  2963.     reg t1, t2;
  2964.     r_mov((short *)get_modrm(), t1);
  2965.     r_add(st(), t1, t2);
  2966.     st() = t2;
  2967.   }
  2968. }
  2969.  
  2970. static void emu_61()
  2971. {
  2972.   if (empty())
  2973.     return;
  2974.   if (modrm > 0277)
  2975.   {
  2976.     // fmulp st(i),st
  2977.     int i = modrm & 7;
  2978.     if (empty(i))
  2979.       return;
  2980.     reg t;
  2981.     r_mul(st(i), st(), t);
  2982.     st(i) = t;
  2983.     st().tag = TW_E;
  2984.     top++;
  2985.   }
  2986.   else
  2987.   {
  2988.     // fimul m16int
  2989.     reg t, t2;
  2990.     r_mov((short *)get_modrm(), t);
  2991.     r_mul(st(), t, t2);
  2992.     st() = t2;
  2993.   }
  2994. }
  2995.  
  2996. static void emu_62()
  2997. {
  2998.   if (empty())
  2999.     return;
  3000.   if (modrm > 0277)
  3001.   {
  3002.     emu_bad();
  3003.   }
  3004.   else
  3005.   {
  3006.     // ficom m16int
  3007.     reg t;
  3008.     r_mov((short *)get_modrm(), t);
  3009.     int c = compare(st(), t);
  3010.     int f;
  3011.     if (c & COMP_NAN)
  3012.     {
  3013.       exception(EX_I);
  3014.       f = SW_C3 | SW_C2 | SW_C0;
  3015.     }
  3016.     else
  3017.       switch (c)
  3018.       {
  3019.         case COMP_A_LT_B:
  3020.           f = SW_C0;
  3021.           break;
  3022.         case COMP_A_EQ_B:
  3023.           f = SW_C3;
  3024.           break;
  3025.         case COMP_A_GT_B:
  3026.           f = 0;
  3027.           break;
  3028.         case COMP_NOCOMP:
  3029.           f = SW_C3 | SW_C2 | SW_C0;
  3030.           break;
  3031.       }
  3032.     setcc(f);
  3033.   }
  3034. }
  3035.  
  3036. static void emu_63()
  3037. {
  3038.   if (empty())
  3039.     return;
  3040.   if (modrm > 0277)
  3041.   {
  3042.     // fcompp
  3043.     if ((modrm&7) != 1)
  3044.       return emu_bad();
  3045.     if (empty(1))
  3046.     {
  3047.       setcc(SW_C3|SW_C2|SW_C0);
  3048.       return;
  3049.     }
  3050.     int c = compare(st(), st(1));
  3051.     int f;
  3052.     st().tag = TW_E;
  3053.     top++;
  3054.     st().tag = TW_E;
  3055.     top++;
  3056.     if (c & COMP_NAN)
  3057.     {
  3058.       exception(EX_I);
  3059.       f = SW_C3 | SW_C2 | SW_C0;
  3060.     }
  3061.     else
  3062.       switch (c)
  3063.       {
  3064.         case COMP_A_LT_B:
  3065.           f = SW_C0;
  3066.           break;
  3067.         case COMP_A_EQ_B:
  3068.           f = SW_C3;
  3069.           break;
  3070.         case COMP_A_GT_B:
  3071.           f = 0;
  3072.           break;
  3073.         case COMP_NOCOMP:
  3074.           f = SW_C3 | SW_C2 | SW_C0;
  3075.           break;
  3076.       }
  3077.     setcc(f);
  3078.     
  3079.   }
  3080.   else
  3081.   {
  3082.     // ficomp m16int
  3083.     reg t;
  3084.     r_mov((short *)get_modrm(), t);
  3085.     int c = compare(st(), t);
  3086.     st().tag = TW_E;
  3087.     top++;
  3088.     int f;
  3089.     if (c & COMP_NAN)
  3090.     {
  3091.       exception(EX_I);
  3092.       f = SW_C3 | SW_C2 | SW_C0;
  3093.     }
  3094.     else
  3095.       switch (c)
  3096.       {
  3097.         case COMP_A_LT_B:
  3098.           f = SW_C0;
  3099.           break;
  3100.         case COMP_A_EQ_B:
  3101.           f = SW_C3;
  3102.           break;
  3103.         case COMP_A_GT_B:
  3104.           f = 0;
  3105.           break;
  3106.         case COMP_NOCOMP:
  3107.           f = SW_C3 | SW_C2 | SW_C0;
  3108.           break;
  3109.       }
  3110.     setcc(f);
  3111.   }
  3112. }
  3113.  
  3114. static void emu_64()
  3115. {
  3116.   if (empty())
  3117.     return;
  3118.   if (modrm > 0277)
  3119.   {
  3120.     // fsubp st(i),st
  3121.     int i = modrm & 7;
  3122.     if (empty(i))
  3123.       return;
  3124.     reg tmp;
  3125.     r_sub(st(), st(i), tmp);
  3126.     st(i) = tmp;
  3127.     st().tag = TW_E;
  3128.     top++;
  3129.     return;
  3130.   }
  3131.   else
  3132.   {
  3133.     // fisub m16int
  3134.     reg t1, t2;
  3135.     r_mov((short *)get_modrm(), t1);
  3136.     r_sub(st(), t1, t2);
  3137.     st() = t2;
  3138.   }
  3139. }
  3140.  
  3141. static void emu_65()
  3142. {
  3143.   if (empty())
  3144.     return;
  3145.   if (modrm > 0277)
  3146.   {
  3147.     // fsubr st(i),st
  3148.     int i = modrm & 7;
  3149.     if (empty(i))
  3150.       return;
  3151.     reg tmp;
  3152.     r_sub(st(i), st(), tmp);
  3153.     st(i) = tmp;
  3154.     st().tag = TW_E;
  3155.     top++;
  3156.     return;
  3157.   }
  3158.   else
  3159.   {
  3160.     // fisubr m16int
  3161.     reg t1, t2;
  3162.     r_mov((short *)get_modrm(), t1);
  3163.     r_sub(t1, st(), t2);
  3164.     st() = t2;
  3165.   }
  3166. }
  3167.  
  3168. static void emu_66()
  3169. {
  3170.   if (empty())
  3171.     return;
  3172.   if (modrm > 0277)
  3173.   {
  3174.     // fdivrp st(i),st
  3175.     int i = modrm & 7;
  3176.     if (empty(i))
  3177.       return;
  3178.     reg t;
  3179.     r_div(st(), st(i), t);
  3180.     st(i) = t;
  3181.     st().tag = TW_E;
  3182.     top++;
  3183.   }
  3184.   else
  3185.   {
  3186.     // fidiv m16int
  3187.     reg t, t2;
  3188.     r_mov((short *)get_modrm(), t);
  3189.     r_div(st(), t, t2);
  3190.     st() = t2;
  3191.   }
  3192. }
  3193.  
  3194. static void emu_67()
  3195. {
  3196.   if (empty())
  3197.     return;
  3198.   if (modrm > 0277)
  3199.   {
  3200.     // fdivp st(i),st
  3201.     reg t;
  3202.     int i = modrm & 7;
  3203.     if (empty(i))
  3204.       return;
  3205.     r_div(st(i), st(), t);
  3206.     st(i) = t;
  3207.     st().tag = TW_E;
  3208.     top++;
  3209.   }
  3210.   else
  3211.   {
  3212.     // fidiv m16int
  3213.     reg t, t2;
  3214.     r_mov((short *)get_modrm(), t);
  3215.     r_div(t, st(), t2);
  3216.     st() = t2;
  3217.   }
  3218. }
  3219.  
  3220. static void emu_70()
  3221. {
  3222.   if (full())
  3223.     return;
  3224.   if (modrm > 0277)
  3225.   {
  3226.     emu_bad();
  3227.   }
  3228.   else
  3229.   {
  3230.     // fild m16int
  3231.     top--;
  3232.     r_mov((short *)get_modrm(), st());
  3233.   }
  3234. }
  3235.  
  3236. static void emu_71()
  3237. {
  3238.   void emu_bad();
  3239.   emu_bad();
  3240. }
  3241.  
  3242.  
  3243. static void emu_72()
  3244. {
  3245.   if (empty())
  3246.     return;
  3247.   if (modrm > 0277)
  3248.   {
  3249.     //
  3250.     emu_bad();
  3251.   }
  3252.   else
  3253.   {
  3254.     // fist m16int
  3255.     r_mov(st(), (short *)get_modrm());
  3256.   }
  3257. }
  3258.  
  3259. static void emu_73()
  3260. {
  3261.   if (empty())
  3262.     return;
  3263.   if (modrm > 0277)
  3264.   {
  3265.     //
  3266.     emu_bad();
  3267.   }
  3268.   else
  3269.   {
  3270.     // fistp m16int
  3271.     r_mov(st(), (short *)get_modrm());
  3272.     st().tag = TW_E;
  3273.     top++;
  3274.   }
  3275. }
  3276.  
  3277. static void fstsw_ax()
  3278. {
  3279.   status_word &= ~SW_TOP;
  3280.   status_word |= (top&7) * SW_TOPS;
  3281.   eax &= 0xffff0000;
  3282.   eax |= status_word;
  3283. }
  3284.  
  3285. static FUNC emu_74_table[] = {
  3286.   fstsw_ax, emu_bad, emu_bad, emu_bad, emu_bad, emu_bad, emu_bad, emu_bad
  3287. };
  3288.  
  3289. static void emu_74()
  3290. {
  3291.   if (modrm > 0277)
  3292.   {
  3293.     (emu_74_table[modrm&7])();
  3294.   }
  3295.   else
  3296.   {
  3297.     // fbld m80dec
  3298.     if (full())
  3299.       return;
  3300.     top--;
  3301.     r_mov((char *)get_modrm(), st());
  3302.   }
  3303. }
  3304.  
  3305. static void emu_75()
  3306. {
  3307.   if (full())
  3308.     return;
  3309.   if (modrm > 0277)
  3310.   {
  3311.     emu_bad();
  3312.   }
  3313.   else
  3314.   {
  3315.     // fild m80int
  3316.     top--;
  3317.     r_mov((long long *)get_modrm(), st());
  3318.   }
  3319. }
  3320.  
  3321. static void emu_76()
  3322. {
  3323.   if (st().tag == TW_E)
  3324.     exception(EX_SU);
  3325.   if (modrm > 0277)
  3326.   {
  3327.     emu_bad();
  3328.   }
  3329.   else
  3330.   {
  3331.     // fbstp
  3332.     r_mov(st(), (char *)get_modrm());
  3333.     st().tag = TW_E;
  3334.     top++;
  3335.   }
  3336. }
  3337.  
  3338. static void emu_77()
  3339. {
  3340.   if (empty())
  3341.     return;
  3342.   if (modrm > 0277)
  3343.   {
  3344.     //
  3345.     emu_bad();
  3346.   }
  3347.   else
  3348.   {
  3349.     // fistp m32int
  3350.     r_mov(st(), (long long *)get_modrm());
  3351.     st().tag = TW_E;
  3352.     top++;
  3353.   }
  3354. }
  3355.  
  3356. #ifndef TEST
  3357. #define TEST 0
  3358. #endif
  3359.  
  3360. extern void emu_install();
  3361. extern void emu_printall();
  3362.  
  3363. #if TEST
  3364.  
  3365. double a=10, b=16;
  3366. float f=3.3;
  3367. int i=3;
  3368.  
  3369. static void test()
  3370. {
  3371.   asm("fldl _b");
  3372.   asm("fldl _a");
  3373.   emu_printall();
  3374.   asm("fdivr %st,%st(1)");
  3375.   emu_printall();
  3376. }
  3377.  
  3378. #endif
  3379.  
  3380. #if 0
  3381. main()
  3382. {
  3383. #if TEST
  3384.   test();
  3385. #endif
  3386.   emu_install();
  3387. #if TEST
  3388.   test();
  3389. #endif
  3390. }
  3391. #endif
  3392.  
  3393. #if 0
  3394. char saw[256*8];
  3395.  
  3396. /* zero here means invalid.  If first entry starts with '*', use st(i) */
  3397. /* no assumed %EFs here.  Indexed by rm(modrm()) */
  3398. char *f0[] = {0, 0, 0, 0, 0, 0, 0, 0};
  3399. char *fop_9[]  = { "*fxch st,%GF" };
  3400. char *fop_10[] = { "fnop", 0, 0, 0, 0, 0, 0, 0 };
  3401. char *fop_12[] = { "fchs", "fabs", 0, 0, "ftst", "fxam", 0, 0 };
  3402. char *fop_13[] = { "fld1", "fldl2t", "fldl2e", "fldpi",
  3403.                    "fldlg2", "fldln2", "fldz", 0 };
  3404. char *fop_14[] = { "f2xm1", "fyl2x", "fptan", "fpatan",
  3405.                    "fxtract", "fprem1", "fdecstp", "fincstp" };
  3406. char *fop_15[] = { "fprem", "fyl2xp1", "fsqrt", "fsincos",
  3407.                    "frndint", "fscale", "fsin", "fcos" };
  3408. char *fop_21[] = { 0, "fucompp", 0, 0, 0, 0, 0, 0 };
  3409. char *fop_28[] = { 0, 0, "fclex", "finit", 0, 0, 0, 0 };
  3410. char *fop_32[] = { "*fadd %GF,st" };
  3411. char *fop_33[] = { "*fmul %GF,st" };
  3412. char *fop_36[] = { "*fsubr %GF,st" };
  3413. char *fop_37[] = { "*fsub %GF,st" };
  3414. char *fop_38[] = { "*fdivr %GF,st" };
  3415. char *fop_39[] = { "*fdiv %GF,st" };
  3416. char *fop_40[] = { "*ffree %GF" };
  3417. char *fop_42[] = { "*fst %GF" };
  3418. char *fop_43[] = { "*fstp %GF" };
  3419. char *fop_44[] = { "*fucom %GF" };
  3420. char *fop_45[] = { "*fucomp %GF" };
  3421. char *fop_48[] = { "*faddp %GF,st" };
  3422. char *fop_49[] = { "*fmulp %GF,st" };
  3423. char *fop_51[] = { 0, "fcompp", 0, 0, 0, 0, 0, 0 };
  3424. char *fop_52[] = { "*fsubrp %GF,st" };
  3425. char *fop_53[] = { "*fsubp %GF,st" };
  3426. char *fop_54[] = { "*fdivrp %GF,st" };
  3427. char *fop_55[] = { "*fdivp %GF,st" };
  3428. char *fop_60[] = { "fstsw ax", 0, 0, 0, 0, 0, 0, 0 };
  3429.  
  3430. char **fspecial[] = { /* 0=use st(i), 1=undefined 0 in fop_* means undefined */
  3431.   0, 0, 0, 0, 0, 0, 0, 0,
  3432.   0, fop_9, fop_10, 0, fop_12, fop_13, fop_14, fop_15,
  3433.   f0, f0, f0, f0, f0, fop_21, f0, f0,
  3434.   f0, f0, f0, f0, fop_28, f0, f0, f0,
  3435.   fop_32, fop_33, f0, f0, fop_36, fop_37, fop_38, fop_39,
  3436.   fop_40, f0, fop_42, fop_43, fop_44, fop_45, f0, f0,
  3437.   fop_48, fop_49, f0, fop_51, fop_52, fop_53, fop_54, fop_55,
  3438.   f0, f0, f0, f0, fop_60, f0, f0, f0,
  3439.   };
  3440.  
  3441. char *floatops[] = { /* assumed " %EF" at end of each.  mod != 3 only */
  3442. /*00*/ "fadd", "fmul", "fcom", "fcomp",
  3443.        "fsub", "fsubr", "fdiv", "fdivr",
  3444. /*08*/ "fld", 0, "fst", "fstp",
  3445.        "fldenv", "fldcw", "fstenv", "fstcw",
  3446. /*16*/ "fiadd", "fimul", "ficomw", "ficompw",
  3447.        "fisub", "fisubr", "fidiv", "fidivr",
  3448. /*24*/ "fild", 0, "fist", "fistp",
  3449.        "frstor", "fldt", 0, "fstpt",
  3450. /*32*/ "faddq", "fmulq", "fcomq", "fcompq",
  3451.        "fsubq", "fsubrq", "fdivq", "fdivrq",
  3452. /*40*/ "fldq", 0, "fstq", "fstpq",
  3453.        0, 0, "fsave", "fstsww",
  3454. /*48*/ "fiaddw", "fimulw", "ficomw", "ficompw",
  3455.        "fisubw", "fisubrw", "fidivw", "fidivr",
  3456. /*56*/ "fildw", 0, "fistw", "fistpw",
  3457.        "fbldt", "fildq", "fbstpt", "fistpq"
  3458.   };
  3459. #endif
  3460.  
  3461. static FUNC esc_table[64] = {
  3462.   emu_00, emu_10, emu_20, emu_30, emu_40, emu_50, emu_60, emu_70,
  3463.   emu_01, emu_11, emu_21, emu_31, emu_41, emu_51, emu_61, emu_71,
  3464.   emu_02, emu_12, emu_22, emu_32, emu_42, emu_52, emu_62, emu_72,
  3465.   emu_03, emu_13, emu_23, emu_33, emu_43, emu_53, emu_63, emu_73,
  3466.   emu_04, emu_14, emu_24, emu_34, emu_44, emu_54, emu_64, emu_74,
  3467.   emu_05, emu_15, emu_25, emu_35, emu_45, emu_55, emu_65, emu_75,
  3468.   emu_06, emu_16, emu_26, emu_36, emu_46, emu_56, emu_66, emu_76,
  3469.   emu_07, emu_17, emu_27, emu_37, emu_47, emu_57, emu_67, emu_77,
  3470. };
  3471.  
  3472. extern "C" int _emu_entry(jmp_buf _exception_state);
  3473.  
  3474. int _emu_entry(jmp_buf _exception_state)
  3475. {
  3476.   int jmpval;
  3477.   eip = (char *) _exception_state->__eip;
  3478.   eax = _exception_state->__eax;
  3479.   ebx = _exception_state->__ebx;
  3480.   ecx = _exception_state->__ecx;
  3481.   edx = _exception_state->__edx;
  3482.   esi = _exception_state->__esi;
  3483.   edi = _exception_state->__edi;
  3484.   ebp = _exception_state->__ebp;
  3485.   esp = _exception_state->__esp;
  3486.   if (*eip == 0x66) // operand size - we know what size we need
  3487.     eip++;
  3488.   if (*eip == 0x9b) // fwait
  3489.   {
  3490. //    _exception_state->__eip++;
  3491.     return 0;
  3492.   }
  3493.   jmpval = setjmp(jumpbuf);
  3494.   if(jmpval)
  3495.     return 1;           /* Emulator failed for some reason */
  3496. #if 0
  3497.   int see = ((int)(eip[0] & 7) << 8) | eip[1];
  3498.   if (saw[see] != 42)
  3499.   {
  3500.     eprintf("EMU387: %02x %02x %02x %02x - e%d%d", eip[0], eip[1], eip[2], eip[3], eip[0]&7, (eip[1]>>3)&7);
  3501.     eprintf(" s%d  ", eip[1]&7);
  3502.     int esc = ((eip[0]<<3)&070) | ((eip[1]>>3)&007);
  3503.     int modrm = eip[1];
  3504.     if ((modrm>>6) == 3)
  3505.       if (fspecial[esc])
  3506.         if (fspecial[esc][0] && (fspecial[esc][0][0] == '*'))
  3507.             eprintf("%s\r\n", fspecial[esc][0]+1);
  3508.         else if (fspecial[esc][modrm&7])
  3509.             eprintf("%s\r\n", fspecial[esc][modrm&7]);
  3510.         else
  3511.           eprintf("<invalid>\r\n");
  3512.       else
  3513.         eprintf("%s st(i)\r\n", floatops[esc]);
  3514.     else
  3515.       eprintf("%s st(i)\r\n", floatops[esc]);
  3516.     saw[see] = 42;
  3517.   }
  3518. #endif
  3519.   int esc_value = *eip++ & 7;
  3520.   modrm = *eip++;
  3521.   esc_value |= (modrm & 070);
  3522.   (esc_table[esc_value])();
  3523. //  emu_printall();
  3524.   _exception_state->__eip = (unsigned long) eip;
  3525.   _exception_state->__eax = eax;
  3526.   return 0;
  3527. }
  3528.